{!isFlipped ? (
- {tableData && tableData.length > 0 ? (
-
- ) : (
-
- )}
+
) : (
@@ -304,22 +303,20 @@ export default function ZonesPanel() {
xDomain,
yDomain,
view: {
- zones: zoneState,
spectra: { activeTab },
},
} = useChartData();
- const { zones, info, id } = useSpectrum(emptyData) as Spectrum2D;
- const zoneProps = zoneState.find((r) => r.spectrumID === id) || zoneStateInit;
+ const { zones, info } = useSpectrum(emptyData) as Spectrum2D;
+ const zoneProps = useActiveSpectrumZonesViewState();
return (
diff --git a/src/component/panels/ZonesPanel/ZonesPreferences.tsx b/src/component/panels/ZonesPanel/ZonesPreferences.tsx
index 3c8505f16..33410d040 100644
--- a/src/component/panels/ZonesPanel/ZonesPreferences.tsx
+++ b/src/component/panels/ZonesPanel/ZonesPreferences.tsx
@@ -18,14 +18,52 @@ import {
NucleusPreferenceField,
} from '../extra/preferences/NucleusPreferences';
import { PreferencesContainer } from '../extra/preferences/PreferencesContainer';
+import { is2DNucleus } from '../../utility/nucleusToString';
-const formatFields: NucleusPreferenceField[] = [
+const preferences1DFields: NucleusPreferenceField[] = [
{
id: 1,
label: 'δ (ppm) :',
checkControllerName: 'deltaPPM.show',
formatControllerName: 'deltaPPM.format',
- hideCheckField: true,
+ },
+];
+const preferences2DFields: NucleusPreferenceField[] = [
+ {
+ id: 1,
+ label: 'Serial number :',
+ checkControllerName: 'showSerialNumber',
+ hideFormatField: true,
+ },
+ {
+ id: 2,
+ label: 'Kind :',
+ checkControllerName: 'showKind',
+ hideFormatField: true,
+ },
+ {
+ id: 3,
+ label: 'Assignment :',
+ checkControllerName: 'showAssignment',
+ hideFormatField: true,
+ },
+ {
+ id: 4,
+ label: 'Delete action :',
+ checkControllerName: 'showDeleteAction',
+ hideFormatField: true,
+ },
+ {
+ id: 5,
+ label: 'Zoom action :',
+ checkControllerName: 'showZoomAction',
+ hideFormatField: true,
+ },
+ {
+ id: 6,
+ label: 'Edit action :',
+ checkControllerName: 'showEditAction',
+ hideFormatField: true,
},
];
@@ -34,8 +72,12 @@ function ZonesPreferences(props, ref) {
const preferences = usePreferences();
const nucleus = useNucleus();
+ const nuclei2D = nucleus.filter((n) => is2DNucleus(n));
const nuclei = useMemo(() => getUniqueNuclei(nucleus), [nucleus]);
- const zonesPreferences = usePanelPreferencesByNuclei('zones', nuclei);
+ const zonesPreferences = usePanelPreferencesByNuclei('zones', [
+ ...nuclei,
+ ...nuclei2D,
+ ]);
useEffect(() => {
void formRef.current?.setValues(zonesPreferences);
@@ -66,7 +108,18 @@ function ZonesPreferences(props, ref) {
<>
{nuclei?.map((n) => (
-
+
+ ))}
+ {nuclei2D?.map((n) => (
+
))}
>
diff --git a/src/component/panels/ZonesPanel/ZonesTable.tsx b/src/component/panels/ZonesPanel/ZonesTable.tsx
index f39b5e22f..275d58b9d 100644
--- a/src/component/panels/ZonesPanel/ZonesTable.tsx
+++ b/src/component/panels/ZonesPanel/ZonesTable.tsx
@@ -8,6 +8,9 @@ import useTableSortBy from '../../hooks/useTableSortBy';
import ZonesTableRow from './ZonesTableRow';
import { useMapZones } from './hooks/useMapZones';
+import NoDataForFid from '../extra/placeholder/NoDataForFid';
+import NoTableData from '../extra/placeholder/NoTableData';
+import { Info2D } from 'nmr-processing';
const tableStyle = css`
border-spacing: 0;
@@ -76,60 +79,88 @@ interface ZonesTableProps {
signalIndex: any,
axis: any,
) => void;
- nuclei: string[];
- experiment: string;
+ nucleus: string;
+ info: Info2D;
}
-function ZonesTable({
- tableData,
- onUnlink,
- nuclei,
- experiment,
-}: ZonesTableProps) {
+function ZonesTable({ tableData, onUnlink, nucleus, info }: ZonesTableProps) {
+ const { experiment, isFid } = info;
+
+ const nuclei = nucleus.split(',');
const data = useMapZones(tableData, { nuclei, experiment });
const { items: sortedData, isSortedDesc, onSort } = useTableSortBy(data);
- const { deltaPPM: deltaX } = usePanelPreferences('zones', nuclei[0]);
- const { deltaPPM: deltaY } = usePanelPreferences('zones', nuclei[1]);
+ const { deltaPPM: deltaX } = usePanelPreferences('zones', nuclei?.[0]);
+ const { deltaPPM: deltaY } = usePanelPreferences('zones', nuclei?.[1]);
+ const {
+ showSerialNumber,
+ showAssignment,
+ showKind,
+ showDeleteAction,
+ showEditAction,
+ showZoomAction,
+ } = usePanelPreferences('zones', nucleus);
+
+ const showActions = showDeleteAction || showEditAction || showZoomAction;
+
+ if (isFid) {
+ return
;
+ }
+
+ if (!tableData || tableData.length === 0) {
+ return
;
+ }
return (
- # |
- δ (ppm) |
-
-
- |
- Σ |
- Kind |
- {''} |
+ {showSerialNumber && # | }
+ {(deltaX.show || deltaX.show) && δ (ppm) | }
+ {showAssignment && (
+ <>
+
+
+ |
+ Σ |
+ >
+ )}
+ {showKind && Kind | }
+ {showActions && {''} | }
-
-
- {nuclei[0]}{' '}
- {isSortedDesc('tableMetaInfo.signal.x.delta').content}
-
- |
-
-
- {nuclei[1]}{' '}
- {isSortedDesc('tableMetaInfo.signal.y.delta').content}
-
- |
-
- {nuclei[0]}
- |
-
- {nuclei[1]}
- |
-
- {nuclei[0]}
- |
-
- {nuclei[1]}
- |
+ {deltaX.show && (
+
+
+ {nuclei[0]}{' '}
+ {isSortedDesc('tableMetaInfo.signal.x.delta').content}
+
+ |
+ )}
+ {deltaY.show && (
+
+
+ {nuclei[1]}{' '}
+ {isSortedDesc('tableMetaInfo.signal.y.delta').content}
+
+ |
+ )}
+ {showAssignment && (
+ <>
+
+ {nuclei[0]}
+ |
+
+ {nuclei[1]}
+ |
+
+ {nuclei[0]}
+ |
+
+ {nuclei[1]}
+ |
+ >
+ )}
@@ -139,7 +170,7 @@ function ZonesTable({
key={`${rowData.tableMetaInfo.id}`}
rowData={rowData}
onUnlink={onUnlink}
- format={{ x: deltaX.format, y: deltaY.format }}
+ nucleus={nucleus}
/>
))}
diff --git a/src/component/panels/ZonesPanel/ZonesTableRow.tsx b/src/component/panels/ZonesPanel/ZonesTableRow.tsx
index 3088d3554..1ac832a1e 100644
--- a/src/component/panels/ZonesPanel/ZonesTableRow.tsx
+++ b/src/component/panels/ZonesPanel/ZonesTableRow.tsx
@@ -18,6 +18,7 @@ import SignalAssignmentsColumns from './TableColumns/SignalAssignmentsColumns';
import SignalDeltaColumn from './TableColumns/SignalDeltaColumn';
import ZoneAssignmentsColumns from './TableColumns/ZoneAssignmentsColumns';
import { ZoneData } from './hooks/useMapZones';
+import { usePanelPreferences } from '../../hooks/usePanelPreferences';
const HighlightedRowStyle: CSSProperties = { backgroundColor: '#ff6f0057' };
@@ -32,7 +33,7 @@ interface ZonesTableRowProps extends ContextMenuProps {
axis: Axis,
) => void;
rowIndex: number;
- format: { x: string; y: string };
+ nucleus: string;
}
function ZonesTableRow({
@@ -41,7 +42,7 @@ function ZonesTableRow({
contextMenu = [],
onContextMenuSelect,
rowIndex,
- format,
+ nucleus,
}: ZonesTableRowProps) {
const assignmentZone = useAssignment(rowData.id);
const highlightZone = useHighlight([assignmentZone.id]);
@@ -66,6 +67,14 @@ function ZonesTableRow({
buildID(assignmentSignal.id, 'Crosshair'),
),
);
+ const {
+ showSerialNumber,
+ showAssignment,
+ showKind,
+ showDeleteAction,
+ showEditAction,
+ showZoomAction,
+ } = usePanelPreferences('zones', nucleus);
const rowSpanTags = useMemo(() => {
return {
@@ -184,35 +193,43 @@ function ZonesTableRow({
}
{...highlightZone.onHover}
>
- {rowIndex + 1} |
+ {showSerialNumber && {rowIndex + 1} | }
-
+
+
+ >
+ )}
+
-
-
);
}
diff --git a/src/component/panels/ZonesPanel/hooks/useMapZones.ts b/src/component/panels/ZonesPanel/hooks/useMapZones.ts
index 6edf73159..8a6d1abaf 100644
--- a/src/component/panels/ZonesPanel/hooks/useMapZones.ts
+++ b/src/component/panels/ZonesPanel/hooks/useMapZones.ts
@@ -19,6 +19,8 @@ export function useMapZones(
): ZoneData[] {
return useMemo(() => {
const zonesData: ZoneData[] = [];
+ if (!data) return [];
+
for (const [i, zone] of data.entries()) {
if (zone.signals.length === 1) {
zonesData.push({
diff --git a/src/component/panels/databasePanel/DatabasePanel.tsx b/src/component/panels/databasePanel/DatabasePanel.tsx
index c68cecc03..e1430dcf8 100644
--- a/src/component/panels/databasePanel/DatabasePanel.tsx
+++ b/src/component/panels/databasePanel/DatabasePanel.tsx
@@ -10,9 +10,6 @@ import {
import { DatabaseNMREntry, mapRanges } from 'nmr-processing';
import OCL from 'openchemlib/full';
import { useCallback, useState, useRef, memo, useEffect, useMemo } from 'react';
-import { BsHexagon, BsHexagonFill } from 'react-icons/bs';
-import { FaICursor } from 'react-icons/fa';
-import { IoSearchOutline } from 'react-icons/io5';
import { useAccordionContext } from 'react-science/ui';
import { isSpectrum1D } from '../../../data/data1d/Spectrum1D';
@@ -27,15 +24,9 @@ import {
import { useChartData } from '../../context/ChartContext';
import { useDispatch } from '../../context/DispatchContext';
import { usePreferences } from '../../context/PreferencesContext';
-import Button from '../../elements/Button';
-import Input from '../../elements/Input';
-import Select from '../../elements/Select';
-import ToggleButton from '../../elements/ToggleButton';
import { useAlert } from '../../elements/popup/Alert';
import { positions, transitions, useModal } from '../../elements/popup/Modal';
import { useFormatNumberByNucleus } from '../../hooks/useFormatNumberByNucleus';
-import useToolsFunctions from '../../hooks/useToolsFunctions';
-import { DISPLAYER_MODE } from '../../reducer/core/Constants';
import { options } from '../../toolbar/ToolTypes';
import Events from '../../utility/Events';
import { exportAsJSON } from '../../utility/export';
@@ -43,21 +34,28 @@ import nucleusToString from '../../utility/nucleusToString';
import { PanelNoData } from '../PanelNoData';
import { tablePanelStyle } from '../extra/BasicPanelStyle';
import NoTableData from '../extra/placeholder/NoTableData';
-import DefaultPanelHeader from '../header/DefaultPanelHeader';
import PreferencesHeader from '../header/PreferencesHeader';
import DatabasePreferences from './DatabasePreferences';
import { DatabaseStructureSearchModal } from './DatabaseStructureSearchModal';
import DatabaseTable from './DatabaseTable';
+import { DatabaseSearchOptions } from './DatabaseSearchOptions';
+
+export type Databases = Array;
export interface DatabaseInnerProps {
nucleus: string;
selectedTool: string;
- databases: Array;
+ databases: Databases;
defaultDatabase: string;
}
-interface ResultEntry {
+export interface DatabaseSearchKeywords {
+ solvent: string;
+ searchKeywords: string;
+}
+
+export interface DataBaseSearchResultEntry {
data: DatabaseNMREntry[];
databases: Array<{ key: string; value: string }>;
solvents: Array<{ label: string; value: string }>;
@@ -87,17 +85,14 @@ function DatabasePanelInner({
const modal = useModal();
const { item } = useAccordionContext('Databases');
- const { handleChangeOption } = useToolsFunctions();
const format = useFormatNumberByNucleus(nucleus);
const [isFlipped, setFlipStatus] = useState(false);
const settingRef = useRef();
- const [keywords, setKeywords] = useState<{
- solvent: string;
- searchKeywords: string;
- }>(emptyKeywords);
+ const [keywords, setKeywords] =
+ useState(emptyKeywords);
const databaseInstance = useRef(null);
const databaseDataRef = useRef([]);
- const [result, setResult] = useState({
+ const [result, setResult] = useState({
data: [],
databases: [],
solvents: [],
@@ -113,18 +108,6 @@ function DatabasePanelInner({
setFlipStatus(false);
}, []);
- const handleSearch = useCallback((input) => {
- if (typeof input === 'string' || input === -1) {
- const solvent = String(input);
- setKeywords((prevState) => ({ ...prevState, solvent }));
- } else {
- setKeywords((prevState) => ({
- ...prevState,
- searchKeywords: input.target.value,
- }));
- }
- }, []);
-
const search = useCallback(
(solvents?: any[]) => {
const { solvent, searchKeywords } = keywords;
@@ -314,18 +297,6 @@ function DatabasePanelInner({
[alert, result],
);
- const clearHandler = useCallback(() => {
- setKeywords((prevState) => ({ ...prevState, searchKeywords: '' }));
- }, []);
-
- const enableFilterHandler = useCallback(
- (flag) => {
- const tool = !flag ? options.zoom.id : options.databaseRangesSelection.id;
- handleChangeOption(tool);
- },
- [handleChangeOption],
- );
-
const searchByStructureHandler = (idCodeValue: string) => {
setIdCode(idCodeValue);
};
@@ -359,74 +330,21 @@ function DatabasePanelInner({
]}
>
{!isFlipped && (
-
+ setKeywords((prevKeywords) => ({ ...prevKeywords, ...options }))
+ }
onSettingClick={settingsPanelHandler}
- canDelete={false}
- >
-
-
-
-
-
- }
- style={{ inputWrapper: { flex: 3 } }}
- className="search-input"
- type="text"
- debounceTime={250}
- placeholder="Search for parameter..."
- onChange={handleSearch}
- onClear={clearHandler}
- canClear
- />
-
- {!idCode ? (
-
- ) : (
-
- )}
-
-
+ onStructureClick={openSearchByStructure}
+ onDatabaseChange={handleChangeDatabase}
+ />
)}
{isFlipped && (
datum.enabled),
- ) as Array;
+ ) as Databases;
- if (!activeTab || displayerMode !== DISPLAYER_MODE.DM_1D) {
+ if (!activeTab || displayerMode !== '1D') {
return (
Databases are only available when 1D experimental spectrum is displayed.
diff --git a/src/component/panels/databasePanel/DatabaseSearchOptions.tsx b/src/component/panels/databasePanel/DatabaseSearchOptions.tsx
new file mode 100644
index 000000000..687284329
--- /dev/null
+++ b/src/component/panels/databasePanel/DatabaseSearchOptions.tsx
@@ -0,0 +1,160 @@
+import { BsHexagon, BsHexagonFill } from 'react-icons/bs';
+import Button from '../../elements/Button';
+import { CounterLabel } from '../../elements/CounterLabel';
+import Input from '../../elements/Input';
+import { PreferencesButton } from '../../elements/PreferencesButton';
+import Select from '../../elements/Select';
+import PanelHeader from '../header/PanelHeader';
+import useToolsFunctions from '../../hooks/useToolsFunctions';
+import { options } from '../../toolbar/ToolTypes';
+import { createFilterLabel } from '../header/DefaultPanelHeader';
+import { FaICursor } from 'react-icons/fa';
+import { IoSearchOutline } from 'react-icons/io5';
+import {
+ DataBaseSearchResultEntry,
+ DatabaseSearchKeywords,
+ Databases,
+} from './DatabasePanel';
+import ToggleButton from '../../elements/ToggleButton';
+
+type OnClick = React.ButtonHTMLAttributes['onClick'];
+
+interface DatabaseSearchOptionsProps {
+ databases: Databases;
+ defaultDatabase: string;
+ keywords: DatabaseSearchKeywords;
+ result: DataBaseSearchResultEntry;
+ selectedTool: string;
+ idCode?: string;
+ total: number;
+ onKeywordsChange: (k: Partial) => void;
+ onSettingClick: OnClick;
+ onStructureClick: OnClick;
+ onDatabaseChange: (databaseKey: string) => void;
+}
+
+export function DatabaseSearchOptions({
+ databases,
+ defaultDatabase,
+ keywords,
+ result,
+ selectedTool,
+ idCode,
+ total,
+ onKeywordsChange,
+ onSettingClick,
+ onStructureClick,
+ onDatabaseChange,
+}: DatabaseSearchOptionsProps) {
+ const { handleChangeOption } = useToolsFunctions();
+
+ function enableFilterHandler(flag) {
+ const tool = !flag ? options.zoom.id : options.databaseRangesSelection.id;
+ handleChangeOption(tool);
+ }
+
+ function handleSearch(input) {
+ if (typeof input === 'string' || input === -1) {
+ const solvent = String(input);
+ onKeywordsChange({ solvent });
+ } else {
+ onKeywordsChange({
+ searchKeywords: input.target.value,
+ });
+ }
+ }
+
+ function clearHandler() {
+ onKeywordsChange({ searchKeywords: '' });
+ }
+
+ return (
+
+
+
+
+
+
+ {createFilterLabel(total || 0, result.data.length)}
+
+
+
+
+
+
+
+
+ }
+ style={{ inputWrapper: { margin: '0 5px', flex: 1 } }}
+ className="search-input"
+ type="text"
+ debounceTime={250}
+ placeholder="Search for parameter..."
+ onChange={handleSearch}
+ onClear={clearHandler}
+ canClear
+ />
+
+ {!idCode ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+}
diff --git a/src/component/panels/extra/placeholder/NoDataForFid.tsx b/src/component/panels/extra/placeholder/NoDataForFid.tsx
new file mode 100644
index 000000000..4dba5a869
--- /dev/null
+++ b/src/component/panels/extra/placeholder/NoDataForFid.tsx
@@ -0,0 +1,5 @@
+import NoTableData from './NoTableData';
+
+export default function NoDataForFid() {
+ return ;
+}
diff --git a/src/component/panels/header/DefaultPanelHeader.tsx b/src/component/panels/header/DefaultPanelHeader.tsx
index 5de08205b..0961eebeb 100644
--- a/src/component/panels/header/DefaultPanelHeader.tsx
+++ b/src/component/panels/header/DefaultPanelHeader.tsx
@@ -1,25 +1,19 @@
import { CSSProperties, ReactNode } from 'react';
-import { FaRegTrashAlt, FaCog, FaFilter } from 'react-icons/fa';
+import { FaRegTrashAlt, FaFilter } from 'react-icons/fa';
import Button from '../../elements/Button';
import ToggleButton from '../../elements/ToggleButton';
-import ToolTip from '../../elements/ToolTip/ToolTip';
import PanelHeader from './PanelHeader';
+import { PreferencesButton } from '../../elements/PreferencesButton';
+import { CounterLabel } from '../../elements/CounterLabel';
-const styles: Record<'leftContainer' | 'counterLabel', CSSProperties> = {
+const styles: Record<'leftContainer', CSSProperties> = {
leftContainer: {
display: 'flex',
flexDirection: 'row',
flex: 1,
},
- counterLabel: {
- margin: 0,
- textAlign: 'right',
- lineHeight: '22px',
- padding: '0 5px',
- whiteSpace: 'nowrap',
- },
};
interface DefaultPanelHeaderProps {
@@ -91,14 +85,8 @@ function DefaultPanelHeader({
{children}
{renderRightButtons?.()}
- {counterLabel && {counterLabel}
}
- {showSettingButton && (
-
-
-
- )}
+ {counterLabel && {counterLabel}}
+ {showSettingButton && }
);
}
diff --git a/src/component/panels/predictionPanel/PredictionPanel.tsx b/src/component/panels/predictionPanel/PredictionPanel.tsx
index 183f5462a..105784297 100644
--- a/src/component/panels/predictionPanel/PredictionPanel.tsx
+++ b/src/component/panels/predictionPanel/PredictionPanel.tsx
@@ -51,7 +51,7 @@ export default function PredictionPanel() {
utils: { toggle: openSpectraPanel },
} = useAccordionContext('Spectra');
const predictionPreferences = usePanelPreferences('prediction');
- const openMoleculeEditor = useMoleculeEditor(true);
+ const { modal, openMoleculeEditor } = useMoleculeEditor(true);
const refreshSlider = useRef(false);
useEffect(() => {
@@ -94,7 +94,10 @@ export default function PredictionPanel() {
);
try {
- const data = await predictSpectra(molfile);
+ const data = await predictSpectra(
+ molfile,
+ predictionPreferences.spectra,
+ );
dispatch({
type: 'PREDICT_SPECTRA',
payload: {
@@ -240,6 +243,7 @@ export default function PredictionPanel() {
>
)}
+ {modal}
);
}
diff --git a/src/component/panels/predictionPanel/PredictionSimpleOptions.tsx b/src/component/panels/predictionPanel/PredictionSimpleOptions.tsx
index 8f9f7ecb0..1409edae1 100644
--- a/src/component/panels/predictionPanel/PredictionSimpleOptions.tsx
+++ b/src/component/panels/predictionPanel/PredictionSimpleOptions.tsx
@@ -9,10 +9,10 @@ import {
} from '../../../data/PredictionManager';
import { usePreferences } from '../../context/PreferencesContext';
import Label, { LabelStyle } from '../../elements/Label';
-import FormikNumberInput from '../../elements/formik/FormikNumberInput';
import FormikOnChange from '../../elements/formik/FormikOnChange';
import FormikSelect from '../../elements/formik/FormikSelect';
import { usePanelPreferences } from '../../hooks/usePanelPreferences';
+import FormikInput from '../../elements/formik/FormikInput';
const predictionFormValidation = Yup.object().shape({
'1d': Yup.object({
@@ -67,10 +67,10 @@ function PredictionSimpleOptions() {
/>
diff --git a/src/component/panels/spectrumSimulation/SpectrumSimulationSimpleOptions.tsx b/src/component/panels/spectrumSimulation/SpectrumSimulationSimpleOptions.tsx
index c4f7e7aa4..93360155f 100644
--- a/src/component/panels/spectrumSimulation/SpectrumSimulationSimpleOptions.tsx
+++ b/src/component/panels/spectrumSimulation/SpectrumSimulationSimpleOptions.tsx
@@ -2,7 +2,7 @@ import { FREQUENCIES } from '../../../data/PredictionManager';
import { getSpinSystems } from '../../../data/data1d/spectrumSimulation';
import Label, { LabelStyle } from '../../elements/Label';
import Select from '../../elements/Select';
-import FormikNumberInput from '../../elements/formik/FormikNumberInput';
+import FormikInput from '../../elements/formik/FormikInput';
import FormikSelect from '../../elements/formik/FormikSelect';
const SPIN_SYSTEMS = getSpinSystems().map((key) => ({
@@ -49,10 +49,15 @@ export default function SpectrumSimulationSimpleOptions({
/>
diff --git a/src/component/reducer/IgnoreActions.ts b/src/component/reducer/IgnoreActions.ts
index bf1c9b6f5..66d5e7956 100644
--- a/src/component/reducer/IgnoreActions.ts
+++ b/src/component/reducer/IgnoreActions.ts
@@ -2,6 +2,7 @@ import { Action } from '../context/DispatchContext';
const ignoreActions = new Set>([
'INITIALIZE_NMRIUM',
+ 'SECRET_THROW_ERROR',
'APPLY_KEY_PREFERENCES',
'BRUSH_END',
'RESET_SELECTED_TOOL',
@@ -26,14 +27,7 @@ const ignoreActions = new Set>([
'TOGGLE_REAL_IMAGINARY_VISIBILITY',
'FLOAT_MOLECULE_OVER_SPECTRUM',
'TOGGLE_SPECTRA_LEGEND',
- 'TOGGLE_PEAKS_VIEW_PROPERTY',
'TOGGLE_MOLECULE_ATOM_NUMBER',
- 'SHOW_J_GRAPH',
- 'SHOW_MULTIPLICITY_TREES',
- 'SHOW_RANGES_INTEGRALS',
- 'SHOW_ZONES',
- 'SHOW_ZONES_PEAKS',
- 'SHOW_ZONES_SIGNALS',
]);
function checkActionType(type: Action['type']): boolean {
diff --git a/src/component/reducer/Reducer.ts b/src/component/reducer/Reducer.ts
index 4694e8737..2b9433365 100644
--- a/src/component/reducer/Reducer.ts
+++ b/src/component/reducer/Reducer.ts
@@ -28,7 +28,6 @@ import * as SpectraAnalysisActions from './actions/SpectraAnalysisAction';
import * as SpectrumsActions from './actions/SpectrumsActions';
import * as ToolsActions from './actions/ToolsActions';
import * as ZonesActions from './actions/ZonesActions';
-import { DISPLAYER_MODE } from './core/Constants';
import { ZoomHistory } from './helper/ZoomHistoryManager';
export interface ActiveSpectrum {
@@ -36,16 +35,8 @@ export interface ActiveSpectrum {
index: number;
}
-export const rangeStateInit = {
- showMultiplicityTrees: false,
- showRangesIntegrals: true,
- showJGraph: false,
-};
-export const zoneStateInit = {
- showZones: true,
- showSignals: true,
- showPeaks: true,
-};
+export type DisplayerMode = '1D' | '2D';
+
export interface Margin {
top: number;
right: number;
@@ -53,11 +44,14 @@ export interface Margin {
left: number;
}
+export type Domains = Record;
+export type SpectraDirection = 'RTL' | 'LTR';
+
export function getDefaultViewState(): ViewState {
return {
molecules: {},
- ranges: [],
- zones: [],
+ ranges: {},
+ zones: {},
peaks: {},
spectra: {
activeSpectra: {},
@@ -109,7 +103,7 @@ export const getInitialState = (): State => ({
},
isLoading: false,
keysPreferences: {},
- displayerMode: DISPLAYER_MODE.DM_1D,
+ displayerMode: '1D',
correlations: {},
displayerKey: '',
zoom: {
@@ -122,6 +116,7 @@ export const getInitialState = (): State => ({
baselineCorrection: {
options: {},
zones: [],
+ livePreview: true,
},
apodizationOptions: {} as ApodizationOptions,
pivot: { value: 0, index: 0 },
@@ -174,13 +169,13 @@ export interface State {
* value change when vertical scale change for the selected spectrum
* @default {}
*/
- yDomains: Record;
+ yDomains: Domains;
/**
* X axis domain per spectrum
* value change when zooming in/out for the selected spectrum
* @default {}
*/
- xDomains: Record;
+ xDomains: Domains;
/**
* Domain for X and Y axis once it calculated and it change in one case when we load new spectra
* @default {}
@@ -188,8 +183,8 @@ export interface State {
originDomain: {
xDomain: number[];
yDomain: number[];
- xDomains: Record;
- yDomains: Record;
+ xDomains: Domains;
+ yDomains: Domains;
shareYDomain: boolean;
};
/**
@@ -218,7 +213,7 @@ export interface State {
* Scale direction
* @default 'RTL'
*/
- mode: 'RTL' | 'LTR';
+ mode: SpectraDirection;
/**
* molecules
* @default []
@@ -255,7 +250,7 @@ export interface State {
* displayer mode '1D' or '2D'
* @default '1D'
*/
- displayerMode: DISPLAYER_MODE;
+ displayerMode: DisplayerMode;
/**
* unique key identifier per Displayer instance
*/
@@ -300,6 +295,7 @@ export interface State {
baselineCorrection: {
zones: BaselineCorrectionZone[];
options: any;
+ livePreview: boolean;
};
apodizationOptions: ApodizationOptions;
/**
@@ -452,7 +448,6 @@ function innerSpectrumReducer(draft: Draft, action: Action) {
return FiltersActions.handleAddExclusionZone(draft, action);
case 'DELETE_EXCLUSION_ZONE':
return FiltersActions.handleDeleteExclusionZone(draft, action);
-
case 'CHANGE_SPECTRUM_VISIBILITY':
return SpectrumsActions.handleChangeSpectrumVisibilityById(
draft,
@@ -586,16 +581,16 @@ function innerSpectrumReducer(draft: Draft, action: Action) {
return RangesActions.handleSetDiaIDRange(draft, action);
case 'UPDATE_RANGE':
return RangesActions.handleUpdateRange(draft, action);
- case 'SHOW_MULTIPLICITY_TREES':
- return RangesActions.handleShowMultiplicityTrees(draft, action);
- case 'SHOW_RANGES_INTEGRALS':
- return RangesActions.handleShowRangesIntegrals(draft, action);
+ case 'TOGGLE_RANGES_VIEW_PROPERTY':
+ return RangesActions.handleToggleRangesViewProperty(draft, action);
case 'AUTO_RANGES_SPECTRA_PICKING':
return RangesActions.handleAutoSpectraRangesDetection(draft);
- case 'SHOW_J_GRAPH':
- return RangesActions.handleShowJGraph(draft, action);
case 'CUT_RANGE':
return RangesActions.handleCutRange(draft, action);
+ case 'TOGGLE_RANGES_PEAKS_DISPLAYING_MODE':
+ return RangesActions.handleChangePeaksDisplayingMode(draft);
+ case 'DELETE_RANGE_PEAK':
+ return RangesActions.handleDeleteRangePeak(draft, action);
case 'SET_KEY_PREFERENCES':
return PreferencesActions.handleSetKeyPreferences(draft, action);
@@ -624,12 +619,8 @@ function innerSpectrumReducer(draft: Draft, action: Action) {
return ZonesActions.handleSetDiaIDZone(draft, action);
case 'AUTO_ZONES_SPECTRA_PICKING':
return ZonesActions.handleAutoSpectraZonesDetection(draft);
- case 'SHOW_ZONES':
- return ZonesActions.handleShowZones(draft, action);
- case 'SHOW_ZONES_SIGNALS':
- return ZonesActions.handleShowSignals(draft, action);
- case 'SHOW_ZONES_PEAKS':
- return ZonesActions.handleShowPeaks(draft, action);
+ case 'TOGGLE_ZONES_VIEW_PROPERTY':
+ return ZonesActions.handleToggleZonesViewProperty(draft, action);
case 'SAVE_EDITED_ZONE':
return ZonesActions.handleSaveEditedZone(draft, action);
@@ -644,6 +635,10 @@ function innerSpectrumReducer(draft: Draft, action: Action) {
case 'SET_AUTOMATIC_ASSIGNMENTS':
return AssignmentsActions.handleSetAutomaticAssignments(draft, action);
+ case 'SECRET_THROW_ERROR': {
+ throw new Error('Error thrown in main reducer');
+ }
+
default:
}
} catch (error: any) {
diff --git a/src/component/reducer/actions/DomainActions.ts b/src/component/reducer/actions/DomainActions.ts
index dbe6f00f8..e37b351ec 100644
--- a/src/component/reducer/actions/DomainActions.ts
+++ b/src/component/reducer/actions/DomainActions.ts
@@ -7,8 +7,8 @@ import { get1DDataXY } from '../../../data/data1d/Spectrum1D/get1DDataXY';
import { isSpectrum2D } from '../../../data/data2d/Spectrum2D';
import nucleusToString from '../../utility/nucleusToString';
import { State } from '../Reducer';
-import { DISPLAYER_MODE } from '../core/Constants';
import { addToBrushHistory } from '../helper/ZoomHistoryManager';
+import { getActiveSpectra } from '../helper/getActiveSpectra';
import { getActiveSpectrum } from '../helper/getActiveSpectrum';
import { ActionType } from '../types/ActionType';
@@ -190,7 +190,7 @@ function setDomain(draft: Draft, options?: SetDomainOptions) {
let domain;
if (draft.view.spectra.activeTab) {
- if (draft.displayerMode === DISPLAYER_MODE.DM_1D) {
+ if (draft.displayerMode === '1D') {
domain = getDomain(draft);
} else {
domain = get2DDomain(draft);
@@ -204,7 +204,7 @@ function setDomain(draft: Draft, options?: SetDomainOptions) {
if (updateYDomain) {
draft.yDomain = domain.yDomain;
- if (draft.displayerMode === DISPLAYER_MODE.DM_1D && isYDomainShared) {
+ if (draft.displayerMode === '1D' && isYDomainShared) {
draft.yDomains = Object.fromEntries(
Object.keys(domain.yDomains).map((key) => {
return [key, domain.yDomain];
@@ -253,12 +253,32 @@ function setIntegralsYDomain(
}
function setMode(draft: Draft) {
- const datum_ = draft.data.find(
- (datum) =>
- draft.xDomains[datum.id] &&
- nucleusToString(datum.info.nucleus) === draft.view.spectra.activeTab,
- );
- draft.mode = (datum_ as Spectrum1D)?.info.isFid ? 'LTR' : 'RTL';
+ const { xDomains, view, data, displayerMode } = draft;
+ const nuclues = view.spectra.activeTab;
+
+ if (displayerMode === '1D') {
+ const datum_ = data.find(
+ (datum) =>
+ xDomains[datum.id] && nucleusToString(datum.info.nucleus) === nuclues,
+ );
+ draft.mode = (datum_ as Spectrum1D)?.info.isFid ? 'LTR' : 'RTL';
+ } else {
+ const activeSpectra = getActiveSpectra(draft);
+ let hasFt = false;
+ if (Array.isArray(activeSpectra) && activeSpectra?.length > 0) {
+ hasFt = activeSpectra.some(
+ (spectrum) => !data[spectrum.index].info.isFid,
+ );
+ } else {
+ hasFt = data.some(
+ (spectrum) =>
+ !spectrum.info.isFid &&
+ nucleusToString(spectrum.info.nucleus) === nuclues,
+ );
+ }
+
+ draft.mode = hasFt ? 'RTL' : 'LTR';
+ }
}
//action
diff --git a/src/component/reducer/actions/FiltersActions.ts b/src/component/reducer/actions/FiltersActions.ts
index 29b890156..813513e31 100644
--- a/src/component/reducer/actions/FiltersActions.ts
+++ b/src/component/reducer/actions/FiltersActions.ts
@@ -21,9 +21,10 @@ import getRange from '../helper/getRange';
import { getStrongestPeak } from '../helper/getStrongestPeak';
import { ActionType } from '../types/ActionType';
-import { setDomain, setMode } from './DomainActions';
+import { setDomain, setIntegralsYDomain, setMode } from './DomainActions';
import { changeSpectrumVerticalAlignment } from './PreferencesActions';
import { activateTool, resetSelectedTool } from './ToolsActions';
+import { getSpectrum } from '../helper/getSpectrum';
const {
fft,
@@ -45,12 +46,20 @@ type ShiftSpectrumAlongXAxisAction = ActionType<
{ shift: number }
>;
type ApodizationFilterAction = ActionType<
- 'APPLY_APODIZATION_FILTER' | 'CALCULATE_APODIZATION_FILTER',
- ApodizationOptions
+ 'APPLY_APODIZATION_FILTER',
+ { options: ApodizationOptions }
+>;
+type ApodizationFilterLiveAction = ActionType<
+ 'CALCULATE_APODIZATION_FILTER',
+ { options: ApodizationOptions; livePreview: boolean }
>;
type ZeroFillingFilterAction = ActionType<
- 'APPLY_ZERO_FILLING_FILTER' | 'CALCULATE_ZERO_FILLING_FILTER',
- { nbPoints: number }
+ 'APPLY_ZERO_FILLING_FILTER',
+ { options: { nbPoints: number } }
+>;
+type ZeroFillingFilterLiveAction = ActionType<
+ 'CALCULATE_ZERO_FILLING_FILTER',
+ { options: { nbPoints: number }; livePreview: boolean }
>;
type ManualPhaseCorrectionFilterAction = ActionType<
| 'APPLY_MANUAL_PHASE_CORRECTION_FILTER'
@@ -58,13 +67,18 @@ type ManualPhaseCorrectionFilterAction = ActionType<
{ ph0: number; ph1: number }
>;
-type BaselineCorrectionFilterProps = Omit<
- BaselineCorrectionOptions,
- 'zones'
-> & { livePreview: boolean };
+type BaselineCorrectionFilterOptions = Omit;
+interface BaselineCorrectionFilterProps {
+ options: BaselineCorrectionFilterOptions;
+ livePreview: boolean;
+}
type BaselineCorrectionFilterAction = ActionType<
- 'APPLY_BASE_LINE_CORRECTION_FILTER' | 'CALCULATE_BASE_LINE_CORRECTION_FILTER',
+ 'APPLY_BASE_LINE_CORRECTION_FILTER',
+ { options: BaselineCorrectionFilterOptions }
+>;
+type BaselineCorrectionFilterLiveAction = ActionType<
+ 'CALCULATE_BASE_LINE_CORRECTION_FILTER',
BaselineCorrectionFilterProps
>;
type EnableFilterAction = ActionType<
@@ -96,9 +110,12 @@ type ApplySignalProcessingAction = ActionType<
export type FiltersActions =
| ShiftSpectrumAlongXAxisAction
| ApodizationFilterAction
+ | ApodizationFilterLiveAction
| ZeroFillingFilterAction
+ | ZeroFillingFilterLiveAction
| ManualPhaseCorrectionFilterAction
| BaselineCorrectionFilterAction
+ | BaselineCorrectionFilterLiveAction
| EnableFilterAction
| DeleteFilterAction
| DeleteSpectraFilterAction
@@ -317,12 +334,37 @@ function updateView(
) {
draft.tempData = null;
const { updateXDomain, updateYDomain } = filterUpdateDomainRules;
+ const spectrum = getSpectrum(draft);
resetSelectedTool(draft);
setDomain(draft, { updateXDomain, updateYDomain });
+ if (spectrum) {
+ setIntegralsYDomain(draft, spectrum);
+ }
setMode(draft);
changeSpectrumVerticalAlignment(draft, { verticalAlign: 'auto-check' });
}
+function disableLivePreview(draft: Draft, id: string) {
+ const activeSpectrum = getActiveSpectrum(draft);
+ if (activeSpectrum) {
+ const index = activeSpectrum.index;
+ const { data } = draft.tempData[index] as Spectrum1D;
+ draft.data[index].data = data;
+ setDomain(draft);
+
+ // reset default options
+ switch (id) {
+ case apodization.name: {
+ draft.toolOptions.data.apodizationOptions = defaultApodizationOptions;
+ break;
+ }
+ default: {
+ return null;
+ }
+ }
+ }
+}
+
//action
function handleShiftSpectrumAlongXAxis(
draft: Draft,
@@ -364,7 +406,7 @@ function handleApplyZeroFillingFilter(
const filters = [
{
name: zeroFilling.id,
- value: action.payload,
+ value: action.payload.options,
},
];
FiltersManager.applyFilter(draft.data[index], filters, {
@@ -386,49 +428,58 @@ function handleApplyZeroFillingFilter(
//action
function handleCalculateZeroFillingFilter(
draft: Draft,
- action: ZeroFillingFilterAction,
+ action: ZeroFillingFilterLiveAction,
) {
const activeSpectrum = getActiveSpectrum(draft);
if (activeSpectrum) {
- const index = activeSpectrum.index;
- const {
- data: { x, re, im },
- filters,
- info,
- } = draft.tempData[index] as Spectrum1D;
-
- const _data = { data: { x, re, im }, filters, info };
- zeroFilling.apply(_data as Spectrum1D, action.payload);
- const { im: newIm, re: newRe, x: newX } = _data.data;
- const datum = draft.data[index] as Spectrum1D;
- datum.data.x = newX;
- datum.data.im = newIm;
- datum.data.re = newRe;
- draft.xDomain = [newX[0], newX.at(-1) as number];
+ const { options, livePreview } = action.payload;
+ if (livePreview) {
+ const index = activeSpectrum.index;
+ const {
+ data: { x, re, im },
+ filters,
+ info,
+ } = draft.tempData[index] as Spectrum1D;
+
+ const _data = { data: { x, re, im }, filters, info };
+ zeroFilling.apply(_data as Spectrum1D, options);
+ const { im: newIm, re: newRe, x: newX } = _data.data;
+ const datum = draft.data[index] as Spectrum1D;
+ datum.data.x = newX;
+ datum.data.im = newIm;
+ datum.data.re = newRe;
+ draft.xDomain = [newX[0], newX.at(-1) as number];
+ } else {
+ disableLivePreview(draft, zeroFilling.name);
+ }
}
}
//action
function handleCalculateApodizationFilter(
draft: Draft,
- action: ApodizationFilterAction,
+ action: ApodizationFilterLiveAction,
) {
const activeSpectrum = getActiveSpectrum(draft);
if (activeSpectrum) {
const index = activeSpectrum.index;
- const options = action.payload;
- const {
- data: { x, re, im },
- info,
- } = draft.tempData[index] as Spectrum1D;
+ const { livePreview, options } = action.payload;
+ if (livePreview) {
+ const {
+ data: { x, re, im },
+ info,
+ } = draft.tempData[index] as Spectrum1D;
- const _data = { data: { x, re, im }, info };
- draft.toolOptions.data.apodizationOptions = options;
- apodization.apply(_data as Spectrum1D, options);
- const { im: newIm, re: newRe } = _data.data;
- const datum = draft.data[index] as Spectrum1D;
- datum.data.im = newIm;
- datum.data.re = newRe;
+ const _data = { data: { x, re, im }, info };
+ draft.toolOptions.data.apodizationOptions = options;
+ apodization.apply(_data as Spectrum1D, options);
+ const { im: newIm, re: newRe } = _data.data;
+ const datum = draft.data[index] as Spectrum1D;
+ datum.data.im = newIm;
+ datum.data.re = newRe;
+ } else {
+ disableLivePreview(draft, apodization.name);
+ }
}
}
@@ -447,7 +498,7 @@ function handleApplyApodizationFilter(
[
{
name: apodization.id,
- value: action.payload,
+ value: action.payload.options,
},
],
{ filterIndex: activeFilterIndex },
@@ -487,6 +538,9 @@ function handleApplyFFTFilter(draft: Draft) {
} else {
updateView(draft, fft.DOMAIN_UPDATE_RULES);
}
+
+ //clear zoom history
+ draft.zoom.history[draft.view.spectra.activeTab] = [];
}
}
@@ -666,7 +720,7 @@ function handleBaseLineCorrectionFilter(
const activeSpectrum = getActiveSpectrum(draft);
if (activeSpectrum) {
const { zones } = draft.toolOptions.data.baselineCorrection;
- const { livePreview, ...options } = action.payload;
+ const { options } = action.payload;
const activeFilterIndex = getActiveFilterIndex(draft);
FiltersManager.applyFilter(
draft.data[activeSpectrum.index],
@@ -709,28 +763,30 @@ function calculateBaseLineCorrection(
// save the baseline options temporary
draft.toolOptions.data.baselineCorrection = {
...draft.toolOptions.data.baselineCorrection,
- ...(baseLineOptions ? { options: baseLineOptions } : {}),
+ ...(baseLineOptions && baseLineOptions),
};
- const { zones, options } = draft.toolOptions.data.baselineCorrection;
- const { livePreview, ...filterOptions } = options;
+ const { zones, options, livePreview } =
+ draft.toolOptions.data.baselineCorrection;
if (livePreview) {
const _data = { data: { x, re, im }, info };
baselineCorrection.apply(_data as Spectrum1D, {
zones,
- ...filterOptions,
+ ...options,
});
const { im: newIm, re: newRe } = _data.data;
const datum = draft.data[index] as Spectrum1D;
datum.data.im = newIm;
datum.data.re = newRe;
+ } else {
+ disableLivePreview(draft, baselineCorrection.id);
}
}
}
//action
function handleCalculateBaseLineCorrection(
draft: Draft,
- action: BaselineCorrectionFilterAction,
+ action: BaselineCorrectionFilterLiveAction,
) {
calculateBaseLineCorrection(draft, action.payload);
}
diff --git a/src/component/reducer/actions/IntegralsActions.ts b/src/component/reducer/actions/IntegralsActions.ts
index a63178890..c6aa5fe62 100644
--- a/src/component/reducer/actions/IntegralsActions.ts
+++ b/src/component/reducer/actions/IntegralsActions.ts
@@ -18,10 +18,10 @@ import {
import { State } from '../Reducer';
import { getActiveSpectrum } from '../helper/getActiveSpectrum';
import getRange from '../helper/getRange';
+import { getSpectrum } from '../helper/getSpectrum';
import { ActionType } from '../types/ActionType';
import { setIntegralsYDomain } from './DomainActions';
-import { getSpectrum } from '../helper/getSpectrum';
type ChangeIntegralSumAction = ActionType<
'CHANGE_INTEGRAL_SUM',
@@ -94,8 +94,8 @@ function addIntegral(datum: Spectrum1D, options: AddIntegralOptions) {
const integration = xyIntegration({ x, y: re }, { from, to, reverse: true });
const integral = {
id: v4(),
- originFrom: from - shiftX,
- originTo: to - shiftX,
+ originalFrom: from - shiftX,
+ originalTo: to - shiftX,
from,
to,
integral: integration,
@@ -172,8 +172,8 @@ function handleChangeIntegral(
if (integralIndex !== -1) {
datum.integrals.values[integralIndex] = {
...integral,
- originFrom: integral.from,
- originTo: integral.to,
+ originalFrom: integral.from,
+ originalTo: integral.to,
absolute: xyIntegration(
{ x, y: re },
{ from: integral.from, to: integral.to, reverse: true },
diff --git a/src/component/reducer/actions/LoadActions.ts b/src/component/reducer/actions/LoadActions.ts
index cf4bdb529..44ce0f477 100644
--- a/src/component/reducer/actions/LoadActions.ts
+++ b/src/component/reducer/actions/LoadActions.ts
@@ -23,6 +23,7 @@ import { ActionType } from '../types/ActionType';
import { changeSpectrumVerticalAlignment } from './PreferencesActions';
import { setSpectraMetaInfo } from './SpectrumsActions';
import { setActiveTab } from './ToolsActions';
+import { StateMoleculeExtended } from '../../../data/molecules/Molecule';
//TODO use viewState type instead of any { view?: ViewState }
interface InitiateProps {
@@ -133,6 +134,7 @@ function setData(
initSpectra(spectra, {
usedColors: draft.usedColors,
onLoadProcessing: autoOnLoadProcessing ? onLoadProcessing : {},
+ molecules: draft.molecules,
}),
);
setCorrelation(draft, correlations);
@@ -149,15 +151,21 @@ function setData(
function initSpectra(
inputSpectra: Spectrum[],
- options: { usedColors: UsedColors; onLoadProcessing: OnLoadProcessing },
+ options: {
+ usedColors: UsedColors;
+ onLoadProcessing: OnLoadProcessing;
+ molecules: StateMoleculeExtended[];
+ },
) {
const spectra: any = [];
- const { usedColors, onLoadProcessing } = options;
+ const { usedColors, onLoadProcessing, molecules } = options;
for (const spectrum of inputSpectra) {
const { info } = spectrum;
if (info.dimension === 1) {
const filters = onLoadProcessing?.[nucleusToString(info.nucleus)] || [];
- spectra.push(initiateDatum1D(spectrum, { usedColors, filters }));
+ spectra.push(
+ initiateDatum1D(spectrum, { usedColors, filters, molecules }),
+ );
} else if (info.dimension === 2) {
spectra.push(initiateDatum2D({ ...spectrum }, { usedColors }));
}
diff --git a/src/component/reducer/actions/MoleculeActions.ts b/src/component/reducer/actions/MoleculeActions.ts
index 1395b3110..3e8557459 100644
--- a/src/component/reducer/actions/MoleculeActions.ts
+++ b/src/component/reducer/actions/MoleculeActions.ts
@@ -19,7 +19,7 @@ import * as MoleculeManager from '../../../data/molecules/MoleculeManager';
import { generateColor } from '../../../data/utilities/generateColor';
import { AssignmentContext } from '../../assignment/AssignmentsContext';
import { State } from '../Reducer';
-import { DISPLAYER_MODE, MARGIN } from '../core/Constants';
+import { MARGIN } from '../core/Constants';
import { ActionType } from '../types/ActionType';
import { unlinkRange } from './RangesActions';
@@ -136,10 +136,10 @@ function removeAssignments(
draft: Draft,
assignmentData: AssignmentContext,
) {
- if (draft.displayerMode === DISPLAYER_MODE.DM_1D) {
+ if (draft.displayerMode === '1D') {
unlinkRange(draft, { assignmentData });
}
- if (draft.displayerMode === DISPLAYER_MODE.DM_2D) {
+ if (draft.displayerMode === '2D') {
unlinkZone(draft, { assignmentData });
}
}
@@ -227,6 +227,7 @@ function checkPredictions(
const { spectra } = inputOptions;
const missing2DPrediction: string[] = [];
const molecule = OCL.Molecule.fromMolfile(molfile);
+ //@ts-expect-error Will be fixed once OCL-utils is typed correctly
const { atoms } = getAtoms(molecule);
for (const [experiment, required] of Object.entries(spectra)) {
if (!required || predictedSpectra[experiment]) continue;
diff --git a/src/component/reducer/actions/PeaksActions.ts b/src/component/reducer/actions/PeaksActions.ts
index ac867c6ea..ad1143522 100644
--- a/src/component/reducer/actions/PeaksActions.ts
+++ b/src/component/reducer/actions/PeaksActions.ts
@@ -2,7 +2,12 @@ import { v4 } from '@lukeed/uuid';
import { NmrData1D } from 'cheminfo-types';
import { Draft, original } from 'immer';
import { xFindClosestIndex } from 'ml-spectra-processing';
-import { Spectrum1D, PeaksViewState } from 'nmr-load-save';
+import {
+ Spectrum1D,
+ PeaksViewState,
+ ViewState,
+ RangesViewState,
+} from 'nmr-load-save';
import { Peak1D, OptionsXYAutoPeaksPicking } from 'nmr-processing';
import {
@@ -17,6 +22,7 @@ import { State } from '../Reducer';
import { getActiveSpectrum } from '../helper/getActiveSpectrum';
import getRange from '../helper/getRange';
import { ActionType } from '../types/ActionType';
+import { defaultRangesViewState } from '../../hooks/useActiveSpectrumRangesViewState';
type AddPeakAction = ActionType<'ADD_PEAK', { x: number }>;
type AddPeaksAction = ActionType<'ADD_PEAKS', { startX: number; endX: number }>;
@@ -239,25 +245,46 @@ function togglePeaksViewProperty(
}
}
}
-function handleChangePeaksDisplayingMode(draft: Draft) {
+
+type TogglePeaksViewState = RangesViewState | PeaksViewState;
+function toggleDisplayingPeaks(
+ draft: Draft,
+ key: keyof Pick,
+) {
const activeSpectrum = getActiveSpectrum(draft);
if (activeSpectrum?.id) {
- const peaksView = draft.view.peaks;
- if (peaksView[activeSpectrum.id]) {
- peaksView[activeSpectrum.id].displayingMode =
- peaksView[activeSpectrum.id].displayingMode === 'single'
+ const viewOptions = draft.view[key];
+ if (viewOptions[activeSpectrum.id]) {
+ viewOptions[activeSpectrum.id].displayingMode =
+ viewOptions[activeSpectrum.id].displayingMode === 'single'
? 'spread'
: 'single';
} else {
- const defaultPeaksView = { ...defaultPeaksViewState };
- defaultPeaksView.displayingMode =
- defaultPeaksView.displayingMode === 'single' ? 'spread' : 'single';
- peaksView[activeSpectrum.id] = defaultPeaksView;
+ let defaultsViewOptions = {} as TogglePeaksViewState;
+ switch (key) {
+ case 'peaks':
+ defaultsViewOptions = { ...defaultPeaksViewState };
+
+ break;
+ case 'ranges':
+ defaultsViewOptions = { ...defaultRangesViewState };
+ break;
+ default:
+ break;
+ }
+
+ defaultsViewOptions.displayingMode =
+ defaultsViewOptions.displayingMode === 'single' ? 'spread' : 'single';
+ viewOptions[activeSpectrum.id] = defaultsViewOptions;
}
}
}
+function handleChangePeaksDisplayingMode(draft: Draft) {
+ toggleDisplayingPeaks(draft, 'peaks');
+}
+
export {
handleAddPeak,
handleAddPeaks,
@@ -267,4 +294,5 @@ export {
handleChangePeakShape,
handleTogglePeaksViewProperty,
handleChangePeaksDisplayingMode,
+ toggleDisplayingPeaks,
};
diff --git a/src/component/reducer/actions/PreferencesActions.ts b/src/component/reducer/actions/PreferencesActions.ts
index 52d58fc3f..1bc1725db 100644
--- a/src/component/reducer/actions/PreferencesActions.ts
+++ b/src/component/reducer/actions/PreferencesActions.ts
@@ -4,7 +4,6 @@ import { Spectrum1D } from 'nmr-load-save';
import groupByInfoKey from '../../utility/GroupByInfoKey';
import nucleusToString from '../../utility/nucleusToString';
import { State, VerticalAlignment } from '../Reducer';
-import { DISPLAYER_MODE } from '../core/Constants';
import { getActiveSpectrum } from '../helper/getActiveSpectrum';
import { ActionType } from '../types/ActionType';
@@ -146,7 +145,7 @@ function handleApplyKeyPreferences(
draft.originDomain = preferences.originDomain;
draft.yDomains = preferences.yDomains;
- if (draft.displayerMode !== DISPLAYER_MODE.DM_2D) {
+ if (draft.displayerMode !== '2D') {
draft.zoom = preferences.zoom;
}
}
diff --git a/src/component/reducer/actions/RangesActions.ts b/src/component/reducer/actions/RangesActions.ts
index 0caf5a2ef..7e009935b 100644
--- a/src/component/reducer/actions/RangesActions.ts
+++ b/src/component/reducer/actions/RangesActions.ts
@@ -2,13 +2,13 @@ import { v4 } from '@lukeed/uuid';
import { Draft, original } from 'immer';
import cloneDeep from 'lodash/cloneDeep';
import { xFindClosestIndex } from 'ml-spectra-processing';
-import { Spectrum, Spectrum1D } from 'nmr-load-save';
+import { RangesViewState, Spectrum, Spectrum1D } from 'nmr-load-save';
import { Signal1D, Range, Filters, FiltersManager } from 'nmr-processing';
import {
- DatumKind,
- SignalKindsToInclude,
-} from '../../../data/constants/SignalsKinds';
+ DATUM_KIND,
+ SIGNAL_INLCUDED_KINDS,
+} from '../../../data/constants/signalsKinds';
import {
addRange,
changeRangeSignal,
@@ -29,16 +29,19 @@ import {
unlinkInAssignmentData,
} from '../../../data/utilities/RangeUtilities';
import { AssignmentContext } from '../../assignment/AssignmentsContext';
+import { defaultRangesViewState } from '../../hooks/useActiveSpectrumRangesViewState';
import { RangeData } from '../../panels/RangesPanel/hooks/useMapRanges';
-import { rangeStateInit, State } from '../Reducer';
+import { FilterType } from '../../utility/filterType';
+import { State } from '../Reducer';
import { getActiveSpectrum } from '../helper/getActiveSpectrum';
import getRange from '../helper/getRange';
+import { getSpectrum } from '../helper/getSpectrum';
import { ActionType } from '../types/ActionType';
import { handleUpdateCorrelations } from './CorrelationsActions';
import { setDomain, setIntegralsYDomain } from './DomainActions';
import { resetSelectedTool } from './ToolsActions';
-import { getSpectrum } from '../helper/getSpectrum';
+import { toggleDisplayingPeaks } from './PeaksActions';
type AutoRangesDetectionAction = ActionType<
'AUTO_RANGES_DETECTION',
@@ -119,12 +122,17 @@ type ChangeRangeSignalValueAction = ActionType<
{ rangeID: string; signalID: string; value: number }
>;
type UpdateRangAction = ActionType<'UPDATE_RANGE', { range: Range }>;
-type ToggleAction = ActionType<
- 'SHOW_MULTIPLICITY_TREES' | 'SHOW_RANGES_INTEGRALS' | 'SHOW_J_GRAPH',
- { id: string }
->;
type CutRangAction = ActionType<'CUT_RANGE', { cutValue: number }>;
+type ToggleRangesViewAction = ActionType<
+ 'TOGGLE_RANGES_VIEW_PROPERTY',
+ {
+ key: keyof FilterType;
+ }
+>;
+
+type DeleteRangePeakAction = ActionType<'DELETE_RANGE_PEAK', { id: string }>;
+
export type RangesActions =
| AutoRangesDetectionAction
| DeleteRangeAction
@@ -139,9 +147,14 @@ export type RangesActions =
| ChangeRangeRelativeValueAction
| ChangeRangeSignalValueAction
| UpdateRangAction
- | ToggleAction
| CutRangAction
- | ActionType<'AUTO_RANGES_SPECTRA_PICKING' | 'CHANGE_RANGES_SUM_FLAG'>;
+ | ToggleRangesViewAction
+ | DeleteRangePeakAction
+ | ActionType<
+ | 'AUTO_RANGES_SPECTRA_PICKING'
+ | 'CHANGE_RANGES_SUM_FLAG'
+ | 'TOGGLE_RANGES_PEAKS_DISPLAYING_MODE'
+ >;
function getRangeIndex(draft: Draft, spectrumIndex, rangeID) {
return (draft.data[spectrumIndex] as Spectrum1D).ranges.values.findIndex(
@@ -160,25 +173,15 @@ function handleAutoRangesDetection(
molecules,
view: {
spectra: { activeTab: nucleus },
- ranges,
},
} = draft;
const activeSpectrum = getActiveSpectrum(draft);
if (activeSpectrum?.id) {
- const { index, id } = activeSpectrum;
+ const { index } = activeSpectrum;
const datum = data[index] as Spectrum1D;
- // add range intial state
- const range = ranges.find((r) => r.spectrumID === id);
- if (!range) {
- ranges.push({
- spectrumID: id,
- ...rangeStateInit,
- });
- }
-
const [from, to] = xDomain;
const windowFromIndex = xFindClosestIndex(datum.data.x, from);
const windowToIndex = xFindClosestIndex(datum.data.x, to);
@@ -276,9 +279,9 @@ function handleChangeRangeSignalKind(
const _range = (draft.data[index] as Spectrum1D).ranges.values[rangeIndex];
if (_range?.signals) {
_range.signals[range.tableMetaInfo.signalIndex].kind = kind;
- _range.kind = SignalKindsToInclude.includes(kind)
- ? DatumKind.signal
- : DatumKind.mixed;
+ _range.kind = SIGNAL_INLCUDED_KINDS.includes(kind)
+ ? DATUM_KIND.signal
+ : DATUM_KIND.mixed;
updateRangesRelativeValues(draft.data[index] as Spectrum1D);
handleUpdateCorrelations(draft);
}
@@ -563,52 +566,31 @@ function handleUpdateRange(draft: Draft, action: UpdateRangAction) {
}
}
-//action
-function handleShowMultiplicityTrees(
+function toggleRangesViewProperty(
draft: Draft,
- action: ToggleAction,
+ key: keyof FilterType,
) {
- const { id } = action.payload;
- const range = draft.view.ranges.find((r) => r.spectrumID === id);
- if (range) {
- range.showMultiplicityTrees = !range.showMultiplicityTrees;
- } else {
- draft.view.ranges.push({
- spectrumID: id,
- ...rangeStateInit,
- showMultiplicityTrees: !rangeStateInit.showMultiplicityTrees,
- });
- }
-}
+ const activeSpectrum = getActiveSpectrum(draft);
-//action
-function handleShowRangesIntegrals(draft: Draft, action: ToggleAction) {
- const { id } = action.payload;
- const range = draft.view.ranges.find((r) => r.spectrumID === id);
- if (range) {
- range.showRangesIntegrals = !range.showRangesIntegrals;
- } else {
- draft.view.ranges.push({
- spectrumID: id,
- ...rangeStateInit,
- showRangesIntegrals: !rangeStateInit.showRangesIntegrals,
- });
+ if (activeSpectrum?.id) {
+ const rangesView = draft.view.ranges;
+ if (rangesView[activeSpectrum.id]) {
+ rangesView[activeSpectrum.id][key] = !rangesView[activeSpectrum.id][key];
+ } else {
+ const defaultRangesView = { ...defaultRangesViewState };
+ defaultRangesView[key] = !defaultRangesView[key];
+ rangesView[activeSpectrum.id] = defaultRangesView;
+ }
}
}
//action
-function handleShowJGraph(draft: Draft, action: ToggleAction) {
- const { id } = action.payload;
- const range = draft.view.ranges.find((r) => r.spectrumID === id);
- if (range) {
- range.showJGraph = !range.showJGraph;
- } else {
- draft.view.ranges.push({
- spectrumID: id,
- ...rangeStateInit,
- showJGraph: !rangeStateInit.showJGraph,
- });
- }
+function handleToggleRangesViewProperty(
+ draft: Draft,
+ action: ToggleRangesViewAction,
+) {
+ const { key } = action.payload;
+ toggleRangesViewProperty(draft, key);
}
function handleCutRange(draft: Draft, action: CutRangAction) {
@@ -630,6 +612,29 @@ function handleCutRange(draft: Draft, action: CutRangAction) {
handleUpdateCorrelations(draft);
}
+function handleChangePeaksDisplayingMode(draft: Draft) {
+ toggleDisplayingPeaks(draft, 'ranges');
+}
+
+//action
+function handleDeleteRangePeak(
+ draft: Draft,
+ action: DeleteRangePeakAction,
+) {
+ const { id } = action.payload;
+ const [rangeKey, signalKey, peakKey] = id.split(',');
+
+ const activeSpectrum = getActiveSpectrum(draft);
+ if (activeSpectrum?.id) {
+ const datum = draft.data[activeSpectrum?.index] as Spectrum1D;
+ const range = datum.ranges.values.find((range) => range.id === rangeKey);
+ const signal = range?.signals.find((singla) => singla.id === signalKey);
+ if (signal) {
+ signal.peaks = signal.peaks?.filter((peak) => peak.id !== peakKey);
+ }
+ }
+}
+
export {
handleCutRange,
handleAutoRangesDetection,
@@ -648,8 +653,8 @@ export {
handleSetDiaIDRange,
handleChangeRangesSumFlag,
handleUpdateRange,
- handleShowMultiplicityTrees,
- handleShowRangesIntegrals,
handleAutoSpectraRangesDetection,
- handleShowJGraph,
+ handleToggleRangesViewProperty,
+ handleChangePeaksDisplayingMode,
+ handleDeleteRangePeak,
};
diff --git a/src/component/reducer/actions/ToolsActions.ts b/src/component/reducer/actions/ToolsActions.ts
index 8925d250d..b402084e0 100644
--- a/src/component/reducer/actions/ToolsActions.ts
+++ b/src/component/reducer/actions/ToolsActions.ts
@@ -8,11 +8,12 @@ import { Nucleus } from '../../../data/types/common/Nucleus';
import { getYScale, getXScale } from '../../1d/utilities/scale';
import { LAYOUT, Layout } from '../../2d/utilities/DimensionLayout';
import { get2DYScale } from '../../2d/utilities/scale';
+import { defaultRangesViewState } from '../../hooks/useActiveSpectrumRangesViewState';
import { Tool, options as Tools } from '../../toolbar/ToolTypes';
import groupByInfoKey from '../../utility/GroupByInfoKey';
import { getSpectraByNucleus } from '../../utility/getSpectraByNucleus';
-import { rangeStateInit, State } from '../Reducer';
-import { DISPLAYER_MODE, MARGIN } from '../core/Constants';
+import { State } from '../Reducer';
+import { MARGIN } from '../core/Constants';
import {
setZoom,
wheelZoom,
@@ -165,17 +166,14 @@ function activateTool(draft, options: ActivateToolOptions) {
if (toolId === Tools.editRange.id) {
const activeSpectrum = getActiveSpectrum(draft);
if (activeSpectrum) {
- const range = draft.view.ranges.find(
- (r) => r.spectrumID === activeSpectrum?.id,
- );
+ const range = draft.view.ranges?.[activeSpectrum?.id];
if (range) {
range.showMultiplicityTrees = true;
} else {
- draft.view.ranges.push({
- spectrumID: activeSpectrum.id,
- ...rangeStateInit,
+ draft.view.ranges[activeSpectrum.id] = {
+ ...defaultRangesViewState,
showMultiplicityTrees: true,
- });
+ };
}
}
}
@@ -283,7 +281,7 @@ function handleToggleRealImaginaryVisibility(draft: Draft) {
}
function handleBrushEnd(draft: Draft, action: BrushEndAction) {
- const is2D = draft.displayerMode === DISPLAYER_MODE.DM_2D;
+ const is2D = draft.displayerMode === '2D';
const { height, margin, yDomain, yDomains, width, xDomains, xDomain, mode } =
draft;
@@ -328,16 +326,11 @@ function setVerticalIndicatorXPosition(
function handleZoom(draft: Draft, action: ZoomAction) {
const { event, trackID, selectedTool } = action.payload;
- const {
- view: { ranges: rangeState },
- displayerMode,
- yDomains,
- integralsYDomains,
- } = draft;
+ const { displayerMode, yDomains, integralsYDomains } = draft;
const activeSpectra = getActiveSpectra(draft);
- if (displayerMode === DISPLAYER_MODE.DM_2D) {
+ if (displayerMode === '2D') {
const index =
trackID === LAYOUT.TOP_1D ? 0 : trackID === LAYOUT.LEFT_1D ? 1 : null;
if (index !== null) {
@@ -352,11 +345,8 @@ function handleZoom(draft: Draft, action: ZoomAction) {
if (selectedTool === Tools.integral.id && event.shiftKey) {
for (const activeSpectrum of activeSpectra) {
//check if the integrals is visible
- const { showRangesIntegrals } =
- rangeState.find((r) => r.spectrumID === activeSpectrum?.id) ||
- rangeStateInit;
const domain = integralsYDomains?.[activeSpectrum?.id];
- if (showRangesIntegrals && domain) {
+ if (domain) {
integralsYDomains[activeSpectrum?.id] = wheelZoom(event, domain);
}
}
@@ -388,7 +378,7 @@ function zoomOut(draft: Draft, action: ZoomOutAction) {
{ xDomain, yDomain },
);
- if (draft.displayerMode === DISPLAYER_MODE.DM_1D) {
+ if (draft.displayerMode === '1D') {
switch (zoomType) {
case ZOOM_TYPES.HORIZONTAL: {
draft.xDomain = xDomain;
@@ -410,6 +400,7 @@ function zoomOut(draft: Draft, action: ZoomOutAction) {
default: {
draft.xDomain = xDomain;
setZoom(draft, { scale: 0.8 });
+ zoomHistory.clear();
break;
}
}
@@ -454,12 +445,12 @@ function setMargin(draft: Draft) {
(activeSpectrum?.id && draft.data[activeSpectrum.index]) || null;
if (
- draft.displayerMode === DISPLAYER_MODE.DM_2D &&
+ draft.displayerMode === '2D' &&
(draft.toolOptions.selectedTool === Tools.slicing.id ||
spectrum?.info.isFid)
) {
draft.margin = MARGIN['2D'];
- } else if (draft.displayerMode === DISPLAYER_MODE.DM_2D) {
+ } else if (draft.displayerMode === '2D') {
const top = hasAcceptedSpectrum(draft, 0)
? MARGIN['2D'].top
: MARGIN['1D'].top;
@@ -467,7 +458,7 @@ function setMargin(draft: Draft) {
? MARGIN['2D'].left
: MARGIN['1D'].left;
draft.margin = { ...MARGIN['2D'], top, left };
- } else if (draft.displayerMode === DISPLAYER_MODE.DM_1D) {
+ } else if (draft.displayerMode === '1D') {
draft.margin = MARGIN['1D'];
}
}
@@ -476,8 +467,8 @@ function setMargin(draft: Draft) {
function setDisplayerMode(draft: Draft, data) {
draft.displayerMode =
data && (data as Spectrum[]).some((d) => d.info.dimension === 2)
- ? DISPLAYER_MODE.DM_2D
- : DISPLAYER_MODE.DM_1D;
+ ? '2D'
+ : '1D';
}
//utility
@@ -625,7 +616,7 @@ function levelChangeHandler(draft: Draft, action: LevelChangeAction) {
}
function setSpectraSameTopHandler(draft: Draft) {
- if (draft.displayerMode === DISPLAYER_MODE.DM_1D) {
+ if (draft.displayerMode === '1D') {
draft.originDomain.shareYDomain = false;
setZoom(draft, { scale: 0.8 });
}
diff --git a/src/component/reducer/actions/ZonesActions.ts b/src/component/reducer/actions/ZonesActions.ts
index 1be6232d9..ea86afd11 100644
--- a/src/component/reducer/actions/ZonesActions.ts
+++ b/src/component/reducer/actions/ZonesActions.ts
@@ -2,14 +2,14 @@ import { FromTo, NmrData2DFt } from 'cheminfo-types';
import { Draft, original } from 'immer';
import lodashCloneDeep from 'lodash/cloneDeep';
import { setPathLength } from 'nmr-correlation';
-import type { Spectrum, Spectrum2D } from 'nmr-load-save';
+import type { Spectrum, Spectrum2D, ZonesViewState } from 'nmr-load-save';
import type { Signal2D, Zone } from 'nmr-processing';
import { Filters, FiltersManager } from 'nmr-processing';
import {
- DatumKind,
- SignalKindsToInclude,
-} from '../../../data/constants/SignalsKinds';
+ DATUM_KIND,
+ SIGNAL_INLCUDED_KINDS,
+} from '../../../data/constants/signalsKinds';
import {
changeZoneSignal,
detectZones,
@@ -23,13 +23,15 @@ import {
import { isNumber } from '../../../data/utilities/isNumber';
import { AssignmentContext, Axis } from '../../assignment/AssignmentsContext';
import { ZoneData } from '../../panels/ZonesPanel/hooks/useMapZones';
-import { State, zoneStateInit } from '../Reducer';
+import { State } from '../Reducer';
import get2DRange, { ZoneBoundary } from '../helper/get2DRange';
import { getActiveSpectrum } from '../helper/getActiveSpectrum';
import { ActionType } from '../types/ActionType';
import { handleUpdateCorrelations } from './CorrelationsActions';
import { setDomain } from './DomainActions';
+import { FilterType } from '../../utility/filterType';
+import { defaultZonesViewState } from '../../hooks/useActiveSpectrumZonesViewState';
interface DeleteSignal2DProps {
spectrum: Spectrum;
@@ -70,12 +72,7 @@ type SetSignalPathLengthAction = ActionType<
pathLength: number | FromTo | undefined;
}
>;
-type ToggleZoneViewPropertyAction = ActionType<
- 'SHOW_ZONES' | 'SHOW_ZONES_SIGNALS' | 'SHOW_ZONES_PEAKS',
- {
- id: string;
- }
->;
+
type SetZoneDiaIDAction = ActionType<
'SET_ZONE_DIAID',
{
@@ -101,6 +98,13 @@ interface UnlinkZoneProps {
type UnlinkZoneAction = ActionType<'UNLINK_ZONE', UnlinkZoneProps>;
+type ToggleZonesViewAction = ActionType<
+ 'TOGGLE_ZONES_VIEW_PROPERTY',
+ {
+ key: keyof FilterType;
+ }
+>;
+
export type ZonesActions =
| AutoZonesDetectionAction
| ChangeZonesFactorAction
@@ -110,10 +114,10 @@ export type ZonesActions =
| DeleteZoneAction
| DeleteSignal2DAction
| SetSignalPathLengthAction
- | ToggleZoneViewPropertyAction
| SetZoneDiaIDAction
| SaveEditedZoneAction
| UnlinkZoneAction
+ | ToggleZonesViewAction
| ActionType<'AUTO_ZONES_SPECTRA_PICKING'>;
//action
@@ -241,9 +245,9 @@ function handleChangeZoneSignalKind(
const zoneIndex = getZoneIndex(state, index, zoneData.id);
const _zone = (draft.data[index] as Spectrum2D).zones.values[zoneIndex];
_zone.signals[zoneData.tableMetaInfo.signalIndex].kind = kind;
- _zone.kind = SignalKindsToInclude.includes(kind)
- ? DatumKind.signal
- : DatumKind.mixed;
+ _zone.kind = SIGNAL_INLCUDED_KINDS.includes(kind)
+ ? DATUM_KIND.signal
+ : DATUM_KIND.mixed;
handleUpdateCorrelations(draft);
}
}
@@ -441,58 +445,32 @@ function handleSaveEditedZone(
handleUpdateCorrelations(draft);
}
}
-//action
-function handleShowZones(
- draft: Draft,
- action: ToggleZoneViewPropertyAction,
-) {
- const { id } = action.payload;
- const zone = draft.view.zones.find((r) => r.spectrumID === id);
- if (zone) {
- zone.showZones = !zone.showZones;
- } else {
- draft.view.zones.push({
- spectrumID: id,
- ...zoneStateInit,
- showZones: !zoneStateInit.showZones,
- });
- }
-}
-//action
-function handleShowSignals(
+function togglePeaksViewProperty(
draft: Draft,
- action: ToggleZoneViewPropertyAction,
+ key: keyof FilterType,
) {
- const { id } = action.payload;
- const zone = draft.view.zones.find((r) => r.spectrumID === id);
- if (zone) {
- zone.showSignals = !zone.showSignals;
- } else {
- draft.view.zones.push({
- spectrumID: id,
- ...zoneStateInit,
- showSignals: !zoneStateInit.showSignals,
- });
+ const activeSpectrum = getActiveSpectrum(draft);
+
+ if (activeSpectrum?.id) {
+ const zonesView = draft.view.zones;
+ if (zonesView[activeSpectrum.id]) {
+ zonesView[activeSpectrum.id][key] = !zonesView[activeSpectrum.id][key];
+ } else {
+ const defaultZonesView = { ...defaultZonesViewState };
+ defaultZonesView[key] = !defaultZonesView[key];
+ zonesView[activeSpectrum.id] = defaultZonesView;
+ }
}
}
//action
-function handleShowPeaks(
+function handleToggleZonesViewProperty(
draft: Draft,
- action: ToggleZoneViewPropertyAction,
+ action: ToggleZonesViewAction,
) {
- const { id } = action.payload;
- const zone = draft.view.zones.find((r) => r.spectrumID === id);
- if (zone) {
- zone.showPeaks = !zone.showPeaks;
- } else {
- draft.view.zones.push({
- spectrumID: id,
- ...zoneStateInit,
- showPeaks: !zoneStateInit.showPeaks,
- });
- }
+ const { key } = action.payload;
+ togglePeaksViewProperty(draft, key);
}
export {
@@ -510,7 +488,5 @@ export {
handleSetSignalPathLength,
handleChangeZonesFactor,
handleAutoSpectraZonesDetection,
- handleShowZones,
- handleShowSignals,
- handleShowPeaks,
+ handleToggleZonesViewProperty,
};
diff --git a/src/component/reducer/core/Constants.ts b/src/component/reducer/core/Constants.ts
index 311eaf16c..969eb2fc2 100644
--- a/src/component/reducer/core/Constants.ts
+++ b/src/component/reducer/core/Constants.ts
@@ -1,8 +1,3 @@
-export enum DISPLAYER_MODE {
- DM_1D = '1D',
- DM_2D = '2D',
-}
-
export const MARGIN = {
'2D': { top: 100, right: 50, bottom: 70, left: 100 },
'1D': {
diff --git a/src/component/reducer/helper/ZoomHistoryManager.ts b/src/component/reducer/helper/ZoomHistoryManager.ts
index c5574e4bd..043a941be 100644
--- a/src/component/reducer/helper/ZoomHistoryManager.ts
+++ b/src/component/reducer/helper/ZoomHistoryManager.ts
@@ -2,7 +2,6 @@ import { Draft } from 'immer';
import { Layout } from '../../2d/utilities/DimensionLayout';
import { State } from '../Reducer';
-import { DISPLAYER_MODE } from '../core/Constants';
interface HistoryItem {
xDomain: number[];
@@ -71,7 +70,7 @@ export function addToBrushHistory(
// eslint-disable-next-line unicorn/consistent-destructuring
draft.view.spectra.activeTab,
);
- if (displayerMode === DISPLAYER_MODE.DM_2D) {
+ if (displayerMode === '2D') {
switch (trackID) {
case 'CENTER_2D':
draft.xDomain = xDomain;
diff --git a/src/component/reducer/preferences/panelsPreferencesDefaultValues.ts b/src/component/reducer/preferences/panelsPreferencesDefaultValues.ts
index cfbe34101..c3349fa31 100644
--- a/src/component/reducer/preferences/panelsPreferencesDefaultValues.ts
+++ b/src/component/reducer/preferences/panelsPreferencesDefaultValues.ts
@@ -3,6 +3,7 @@ import {
PanelsPreferences,
SpectraNucleusPreferences,
} from 'nmr-load-save';
+import { is2DNucleus } from '../../utility/nucleusToString';
function getPreferences(data: T, nucleus?: string) {
return { nuclei: { ...(nucleus ? { [nucleus]: data } : {}) } };
@@ -59,27 +60,53 @@ const getIntegralDefaultValues = (
nucleus?: string,
): PanelsPreferences['integrals'] => {
const preferences = {
+ showSerialNumber: true,
absolute: { show: false, format: '0.00' },
relative: { show: true, format: '0.00' },
+ from: { show: true, format: '0.00' },
+ to: { show: true, format: '0.00' },
color: '#000000',
strokeWidth: 1,
showKind: true,
+ showDeleteAction: true,
};
+
return getPreferences(preferences, nucleus);
};
-const getZoneDefaultValues = (
- nucleus?: string,
-): PanelsPreferences['zones'] => ({
- absolute: { show: false, format: '0.00' },
- relative: { show: true, format: '0.00' },
- ...getPreferences({ deltaPPM: { show: true, format: '0.00' } }, nucleus),
-});
+const getZoneDefaultValues = (nucleus?: string): PanelsPreferences['zones'] => {
+ const common = {
+ absolute: { show: false, format: '0.00' },
+ relative: { show: true, format: '0.00' },
+ };
+
+ if (!nucleus) {
+ return { nuclei: {} };
+ }
+
+ if (is2DNucleus(nucleus)) {
+ const perferences2D = {
+ showSerialNumber: true,
+ showKind: true,
+ showDeleteAction: true,
+ showZoomAction: true,
+ showEditAction: true,
+ showAssignment: true,
+ };
+ return { ...common, ...getPreferences(perferences2D, nucleus) };
+ } else {
+ const perferences1D = {
+ deltaPPM: { show: true, format: '0.00' },
+ };
+ return { ...common, ...getPreferences(perferences1D, nucleus) };
+ }
+};
const getRangeDefaultValues = (
nucleus?: string,
): PanelsPreferences['ranges'] => {
const preferences = {
+ showSerialNumber: true,
from: { show: false, format: '0.00' },
to: { show: false, format: '0.00' },
absolute: { show: false, format: '0.00' },
@@ -89,6 +116,11 @@ const getRangeDefaultValues = (
coupling: { show: true, format: '0.00' },
jGraphTolerance: nucleus === '1H' ? 0.2 : nucleus === '13C' ? 2 : 0, //J Graph tolerance for: 1H: 0.2Hz 13C: 2Hz
showKind: true,
+ showMultiplicity: true,
+ showAssignment: true,
+ showDeleteAction: true,
+ showZoomAction: true,
+ showEditAction: true,
};
return getPreferences(preferences, nucleus);
@@ -98,14 +130,16 @@ const getPeaksDefaultValues = (
nucleus?: string,
): PanelsPreferences['peaks'] => {
const preferences = {
- peakNumber: { show: true, format: '0' },
+ showSerialNumber: true,
deltaPPM: { show: true, format: '0.00' },
deltaHz: { show: false, format: '0.00' },
peakWidth: { show: false, format: '0.00' },
intensity: { show: true, format: '0.00' },
- showKind: true,
fwhm: { show: true, format: '0.00000' },
mu: { show: false, format: '0.00000' },
+ showDeleteAction: true,
+ showEditPeakShapeAction: true,
+ showKind: true,
};
return getPreferences(preferences, nucleus);
diff --git a/src/component/toolbar/ToolTypes.ts b/src/component/toolbar/ToolTypes.ts
index 7c8170ae2..c42e580c1 100644
--- a/src/component/toolbar/ToolTypes.ts
+++ b/src/component/toolbar/ToolTypes.ts
@@ -1,15 +1,14 @@
import { NMRiumToolBarPreferences } from 'nmr-load-save';
import type { Info1D, Info2D } from 'nmr-processing';
import { Filters } from 'nmr-processing';
-
-import { DISPLAYER_MODE } from '../reducer/core/Constants';
+import { DisplayerMode } from '../reducer/Reducer';
type InfoKey = keyof Info1D | keyof Info2D;
export interface ToolOptionItem {
id: string;
label: string;
- mode?: DISPLAYER_MODE;
+ mode?: DisplayerMode;
spectraOptions?: Array<
| {
info?: Array<{ key: InfoKey; value: any }>; // check if the active spectrum has these info
@@ -47,7 +46,7 @@ export const options: RecordOptions = {
label: 'Peaks picking',
hasOptionPanel: true,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -61,7 +60,7 @@ export const options: RecordOptions = {
label: 'Integral Tool',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -75,7 +74,7 @@ export const options: RecordOptions = {
label: 'Zone tool',
hasOptionPanel: true,
isFilter: false,
- mode: DISPLAYER_MODE.DM_2D,
+ mode: '2D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -89,7 +88,7 @@ export const options: RecordOptions = {
label: 'Slicing tool',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_2D,
+ mode: '2D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -103,7 +102,7 @@ export const options: RecordOptions = {
label: 'Move spectrum horizontally',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -117,7 +116,7 @@ export const options: RecordOptions = {
label: 'Equalizer tool',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -131,7 +130,7 @@ export const options: RecordOptions = {
label: 'Range picking and multiplet analysis',
hasOptionPanel: true,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -145,7 +144,7 @@ export const options: RecordOptions = {
label: Filters.apodization.name,
hasOptionPanel: true,
isFilter: true,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [
@@ -162,7 +161,7 @@ export const options: RecordOptions = {
label: Filters.zeroFilling.name,
hasOptionPanel: true,
isFilter: true,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [
@@ -179,7 +178,7 @@ export const options: RecordOptions = {
label: Filters.phaseCorrection.name,
hasOptionPanel: true,
isFilter: true,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [
@@ -196,7 +195,7 @@ export const options: RecordOptions = {
label: Filters.baselineCorrection.name,
hasOptionPanel: true,
isFilter: true,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -210,7 +209,7 @@ export const options: RecordOptions = {
label: 'range general selector',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -225,7 +224,7 @@ export const options: RecordOptions = {
label: 'edit range',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -240,7 +239,7 @@ export const options: RecordOptions = {
label: 'Multiple spectra analysis',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -257,7 +256,7 @@ export const options: RecordOptions = {
label: 'Exclusion zones',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -274,7 +273,7 @@ export const options: RecordOptions = {
label: 'Matrix generations exclusion zones',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -291,7 +290,7 @@ export const options: RecordOptions = {
label: 'Filter database',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
@@ -312,7 +311,7 @@ export const options: RecordOptions = {
label: 'Fourier transform',
hasOptionPanel: false,
isFilter: true,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [
@@ -329,7 +328,7 @@ export const options: RecordOptions = {
label: 'Fourier transform dimension 1',
hasOptionPanel: false,
isFilter: true,
- mode: DISPLAYER_MODE.DM_2D,
+ mode: '2D',
spectraOptions: [
{
info: [
@@ -347,7 +346,7 @@ export const options: RecordOptions = {
label: 'Fourier transform dimension 2',
hasOptionPanel: false,
isFilter: true,
- mode: DISPLAYER_MODE.DM_2D,
+ mode: '2D',
spectraOptions: [
{
info: [
@@ -372,7 +371,7 @@ export const options: RecordOptions = {
label: 'Real / Imaginary',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isComplex', value: true }],
@@ -386,7 +385,7 @@ export const options: RecordOptions = {
label: 'Align spectrum',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
isToggle: false,
},
spectraStackAlignments: {
@@ -394,7 +393,7 @@ export const options: RecordOptions = {
label: 'Stack spectra',
hasOptionPanel: false,
isFilter: false,
- mode: DISPLAYER_MODE.DM_1D,
+ mode: '1D',
spectraOptions: [
{
info: [{ key: 'isFt', value: true }],
diff --git a/src/component/utility/export.ts b/src/component/utility/export.ts
index ab0d3d8ab..fcb9c1bb9 100644
--- a/src/component/utility/export.ts
+++ b/src/component/utility/export.ts
@@ -1,3 +1,4 @@
+import { SerializedStyles } from '@emotion/react';
import { saveAs } from 'file-saver';
import JSZip from 'jszip';
@@ -165,8 +166,12 @@ function copyBlobToClipboard(canvas: HTMLCanvasElement) {
});
}
-function copyPNGToClipboard(rootRef: HTMLDivElement, elementID: string) {
- const { blob, width, height } = getBlob(rootRef, elementID);
+function copyPNGToClipboard(
+ rootRef: HTMLDivElement,
+ elementID: string,
+ css?: SerializedStyles,
+) {
+ const { blob, width, height } = getBlob(rootRef, elementID, css);
try {
const canvas = document.createElement('canvas');
canvas.width = width;
@@ -203,7 +208,11 @@ export interface BlobObject {
height: number;
}
-function getBlob(rootRef: HTMLDivElement, elementID: string): BlobObject {
+function getBlob(
+ rootRef: HTMLDivElement,
+ elementID: string,
+ css?: SerializedStyles,
+): BlobObject {
const _svg: any = (rootRef.getRootNode() as Document)
.querySelector(`#${elementID}`)
?.cloneNode(true);
@@ -218,19 +227,20 @@ function getBlob(rootRef: HTMLDivElement, elementID: string): BlobObject {
const floatingMoleculesGroup = getMoleculesElement(rootRef);
_svg.append(floatingMoleculesGroup);
- const head = ``;
const blob = new Blob([svg], { type: 'image/svg+xml' });
diff --git a/src/component/utility/getSpectraObjectPaths.ts b/src/component/utility/getSpectraObjectPaths.ts
index f130b4874..c09752360 100644
--- a/src/component/utility/getSpectraObjectPaths.ts
+++ b/src/component/utility/getSpectraObjectPaths.ts
@@ -1,8 +1,9 @@
import { Spectrum } from 'nmr-load-save';
-export function getSpectraObjectPaths(spectra: Spectrum[]) {
- const keys = ['display', 'meta', 'info', 'customInfo'];
-
+export function getSpectraObjectPaths(
+ spectra: Spectrum[],
+ keys: Array = ['display', 'meta', 'info', 'customInfo'],
+) {
const paths = {};
for (const spectrum of spectra) {
diff --git a/src/component/utility/nucleusToString.ts b/src/component/utility/nucleusToString.ts
index 7db597dea..dba6159e8 100644
--- a/src/component/utility/nucleusToString.ts
+++ b/src/component/utility/nucleusToString.ts
@@ -1,3 +1,7 @@
+export function is2DNucleus(nucleus: string) {
+ return nucleus.includes(',');
+}
+
export default function nucleusToString(nucleus) {
return typeof nucleus === 'string' ? nucleus : nucleus.join(',');
}
diff --git a/src/component/workspaces/embedded.ts b/src/component/workspaces/embedded.ts
index 9cf791179..32daeef9b 100644
--- a/src/component/workspaces/embedded.ts
+++ b/src/component/workspaces/embedded.ts
@@ -7,6 +7,11 @@ export const embedded: InnerWorkspace = {
general: {
experimentalFeatures: { display: true },
hidePanelOnLoad: true,
+ hideHelp: true,
+ hideLogs: true,
+ hideMaximize: true,
+ hideWorkspaces: true,
+ hideGeneralSettings: true,
},
panels: {
@@ -20,6 +25,7 @@ export const embedded: InnerWorkspace = {
zonesPanel: { display: true, open: false },
},
toolBarButtons: {
+ peakPicking: true,
baselineCorrection: true,
exclusionZones: true,
exportAs: true,
diff --git a/src/component/workspaces/exercise.ts b/src/component/workspaces/exercise.ts
index f0179ec3f..bea7bff18 100644
--- a/src/component/workspaces/exercise.ts
+++ b/src/component/workspaces/exercise.ts
@@ -41,18 +41,26 @@ export const exercise: InnerWorkspace = {
integrals: {
nuclei: {
'1H': {
+ showSerialNumber: true,
relative: { show: true, format: '0.00' },
absolute: { show: false, format: '0.00' },
+ from: { show: true, format: '0.00' },
+ to: { show: true, format: '0.00' },
color: 'black',
strokeWidth: 1,
showKind: false,
+ showDeleteAction: true,
},
'13C': {
+ showSerialNumber: true,
relative: { show: true, format: '0.00' },
absolute: { show: false, format: '0.00' },
+ from: { show: true, format: '0.00' },
+ to: { show: true, format: '0.00' },
color: 'black',
strokeWidth: 1,
showKind: false,
+ showDeleteAction: true,
},
},
},
diff --git a/src/component/workspaces/workspaceDefaultProperties.ts b/src/component/workspaces/workspaceDefaultProperties.ts
index 641423d3c..e0694c355 100644
--- a/src/component/workspaces/workspaceDefaultProperties.ts
+++ b/src/component/workspaces/workspaceDefaultProperties.ts
@@ -8,6 +8,9 @@ export const workspaceDefaultProperties: Required = {
experimentalFeatures: { display: false },
hidePanelOnLoad: false,
hideLogs: false,
+ hideHelp: false,
+ hideMaximize: false,
+ hideWorkspaces: false,
},
panels: {
diff --git a/src/data/PredictionManager.ts b/src/data/PredictionManager.ts
index 47aea9ec7..dfd9c9948 100644
--- a/src/data/PredictionManager.ts
+++ b/src/data/PredictionManager.ts
@@ -5,18 +5,20 @@ import { Spectrum } from 'nmr-load-save';
import {
Signal2D,
Zone,
- predictAll,
+ predict,
signalsToXY,
signals2DToZ,
getFrequency,
- PredictedAll,
+ Predicted,
signalsToRanges,
Prediction1D,
Prediction2D,
+ PredictionBase1D,
+ PredictionBase2D,
} from 'nmr-processing';
import OCL from 'openchemlib/full';
-import { DatumKind } from './constants/SignalsKinds';
+import { DATUM_KIND } from './constants/signalsKinds';
import {
initiateDatum1D,
mapRanges,
@@ -28,7 +30,7 @@ import { adjustAlpha } from './utilities/generateColor';
export type Experiment = 'proton' | 'carbon' | 'cosy' | 'hsqc' | 'hmbc';
export type SpectraPredictionOptions = Record;
export type PredictedSpectraResult = Partial<
- Record
+ Record
>;
export interface PredictionOptions {
@@ -86,17 +88,18 @@ export const FREQUENCIES: Array<{ value: number; label: string }> = [
{ value: 1200, label: '1200 MHz' },
];
-const baseURL = 'https://nmr-prediction.service.zakodium.com';
-
-export async function predictSpectra(molfile: string): Promise {
+export async function predictSpectra(
+ molfile: string,
+ options: any,
+): Promise {
const molecule = OCL.Molecule.fromMolfile(molfile);
- return predictAll(molecule, {
- predictOptions: {
- C: {
- webserviceURL: `${baseURL}/v1/predict/carbon`,
- },
- },
- });
+ const predictOptions = {};
+ for (const key in options) {
+ if (!options[key]) continue;
+ const experiment = key === 'proton' ? 'H' : key === 'carbon' ? 'C' : key;
+ predictOptions[experiment] = {};
+ }
+ return predict(molecule, { predictOptions });
}
function generateName(
@@ -294,8 +297,8 @@ function mapZones(zones: Array>) {
return {
id: id || v4(),
kind: 'signal',
- x: { ...x, originDelta: x.delta || 0 },
- y: { ...y, originDelta: y.delta || 0 },
+ x: { ...x, originalDelta: x.delta || 0 },
+ y: { ...y, originalDelta: y.delta || 0 },
...resSignal,
};
});
@@ -303,7 +306,7 @@ function mapZones(zones: Array>) {
id: v4(),
...resZone,
signals: newSignals,
- kind: DatumKind.signal,
+ kind: DATUM_KIND.signal,
};
});
}
diff --git a/src/data/constants/References.ts b/src/data/constants/References.ts
index aa215fb49..e316aaeb7 100644
--- a/src/data/constants/References.ts
+++ b/src/data/constants/References.ts
@@ -5,7 +5,11 @@ interface ReferenceInfo {
delta: number;
}
-export const REFERENCES: Record> = {
+export type OneHReferences = 'tms' | 'tsp' | 'glucose';
+
+export const REFERENCES:
+ | Record<'1H', Record>
+ | Record<'13C', any> = {
'1H': {
tms: {
from: -0.1,
@@ -29,9 +33,12 @@ export const REFERENCES: Record> = {
'13C': {},
};
-export function getRange(
- options: { nucleus?: string; reference?: string } = {},
-): ReferenceInfo {
+export interface GetRangeOptions {
+ nucleus?: string;
+ reference?: string;
+}
+
+export function getRange(options: GetRangeOptions = {}): ReferenceInfo {
const { nucleus = '1H', reference = 'tms' } = options;
if (!REFERENCES[nucleus]) {
diff --git a/src/data/constants/SignalsKinds.ts b/src/data/constants/SignalsKinds.ts
deleted file mode 100644
index 934a545a1..000000000
--- a/src/data/constants/SignalsKinds.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-export const SignalKinds: Array<{ label: string; value: string }> = [
- {
- label: 'Signal',
- value: 'signal',
- },
- {
- label: 'Reference',
- value: 'reference',
- },
- {
- label: 'Solvent',
- value: 'solvent',
- },
- {
- label: 'Impurity',
- value: 'impurity',
- },
- {
- label: 'Standard',
- value: 'standard',
- },
- {
- label: 'P1',
- value: 'p1',
- },
- {
- label: 'P2',
- value: 'p2',
- },
- {
- label: 'P3',
- value: 'p3',
- },
-];
-
-export const SignalKindsToInclude = ['signal'];
-export const DatumKind = { signal: 'signal', mixed: 'mixed' };
diff --git a/src/data/constants/signalsKinds.ts b/src/data/constants/signalsKinds.ts
new file mode 100644
index 000000000..2cee5c60c
--- /dev/null
+++ b/src/data/constants/signalsKinds.ts
@@ -0,0 +1,26 @@
+import { stringCapitalize } from '../../utils/stringCapitalize';
+import { SignalKind } from '../types/common/SignalKind';
+
+const KINDS: SignalKind[] = [
+ 'undefined',
+ 'signal',
+ 'reference',
+ 'solvent',
+ 'standard',
+ 'p1',
+ 'p2',
+ 'p3',
+];
+
+interface SignalKindItem {
+ value: SignalKind;
+ label: string;
+}
+
+export const SIGNAL_KINDS: SignalKindItem[] = KINDS.map((key) => ({
+ value: key,
+ label: stringCapitalize(key),
+}));
+
+export const SIGNAL_INLCUDED_KINDS: SignalKind[] = ['signal'];
+export const DATUM_KIND = { signal: 'signal', mixed: 'mixed' } as const;
diff --git a/src/data/data1d/Spectrum1D/SumManager.ts b/src/data/data1d/Spectrum1D/SumManager.ts
index 8c41011fc..197b19e14 100644
--- a/src/data/data1d/Spectrum1D/SumManager.ts
+++ b/src/data/data1d/Spectrum1D/SumManager.ts
@@ -19,8 +19,16 @@ export interface SumParams {
export type SetSumOptions = Omit;
-export function initSumOptions(options: SumOptions, params: SumParams) {
- let newOptions = { ...options };
+export function initSumOptions(
+ options: Partial,
+ params: SumParams,
+) {
+ let newOptions: SumOptions = {
+ sum: undefined,
+ isSumConstant: true,
+ sumAuto: true,
+ ...options,
+ };
const { molecules, nucleus } = params;
if (options.sumAuto && Array.isArray(molecules) && molecules.length > 0) {
diff --git a/src/data/data1d/Spectrum1D/getReferenceShift.ts b/src/data/data1d/Spectrum1D/getReferenceShift.ts
index a0019950b..73025853e 100644
--- a/src/data/data1d/Spectrum1D/getReferenceShift.ts
+++ b/src/data/data1d/Spectrum1D/getReferenceShift.ts
@@ -5,6 +5,16 @@ import { xFindClosestIndex } from 'ml-spectra-processing';
import { getRange } from '../../constants/References';
+export interface CalibrateOptions {
+ from: number;
+ to: number;
+ nbPeaks: number;
+ targetX: number;
+}
+export interface GetReferenceShiftOptions extends CalibrateOptions {
+ reference?: string;
+}
+
/**
*
* @param {*} datum1D
@@ -16,7 +26,7 @@ import { getRange } from '../../constants/References';
* @param {number} [options.targetX]
* @param {string} [options.reference]
*/
-export function getReferenceShift(datum1D, options) {
+export function getReferenceShift(datum1D, options: GetReferenceShiftOptions) {
const { reference } = options;
let { from, to, nbPeaks, targetX } = options;
if (reference) {
diff --git a/src/data/data1d/Spectrum1D/initiateDatum1D.ts b/src/data/data1d/Spectrum1D/initiateDatum1D.ts
index 76582be94..60b24f5f9 100644
--- a/src/data/data1d/Spectrum1D/initiateDatum1D.ts
+++ b/src/data/data1d/Spectrum1D/initiateDatum1D.ts
@@ -9,19 +9,22 @@ import { get1DColor } from './get1DColor';
import { initiateIntegrals } from './integrals/initiateIntegrals';
import { initiatePeaks } from './peaks/initiatePeaks';
import { initiateRanges } from './ranges/initiateRanges';
+import { initSumOptions } from './SumManager';
+import { StateMoleculeExtended } from '../../molecules/Molecule';
export interface InitiateDatum1DOptions {
usedColors?: UsedColors;
filters?: any[];
+ molecules?: StateMoleculeExtended[];
}
export function initiateDatum1D(
spectrum: any,
options: InitiateDatum1DOptions = {},
): Spectrum1D {
- const { usedColors = {}, filters = [] } = options;
+ const { usedColors = {}, filters = [], molecules = [] } = options;
- const { ranges, ...restSpectrum } = spectrum;
+ const { integrals, ranges, ...restSpectrum } = spectrum;
const spectrumObj: Spectrum1D = { ...restSpectrum };
spectrumObj.id = spectrum.id || v4();
@@ -52,18 +55,34 @@ export function initiateDatum1D(
spectrumObj.filters = Object.assign([], spectrum.filters); //array of object {name: "FilterName", options: FilterOptions = {value | object} }
+ const { nucleus } = spectrumObj.info;
+
spectrumObj.peaks = initiatePeaks(spectrum, spectrumObj);
// array of object {index: xIndex, xShift}
// in case the peak does not exactly correspond to the point value
// we can think about a second attributed `xShift`
- spectrumObj.integrals = initiateIntegrals(spectrum, spectrumObj); // array of object (from: xIndex, to: xIndex)
- spectrumObj.ranges = initiateRanges(spectrum, spectrumObj);
+ const integralsOptions = initSumOptions(integrals?.options || {}, {
+ nucleus,
+ molecules,
+ });
+ spectrumObj.integrals = initiateIntegrals(
+ spectrum,
+ spectrumObj,
+ integralsOptions,
+ ); // array of object (from: xIndex, to: xIndex)
+
+ const rangesOptions = initSumOptions(ranges?.options || {}, {
+ nucleus,
+ molecules,
+ });
+ spectrumObj.ranges = initiateRanges(spectrum, spectrumObj, rangesOptions);
//reapply filters after load the original data
FiltersManager.reapplyFilters(spectrumObj);
preprocessing(spectrumObj, filters);
+
return spectrumObj;
}
diff --git a/src/data/data1d/Spectrum1D/integrals/initiateIntegrals.ts b/src/data/data1d/Spectrum1D/integrals/initiateIntegrals.ts
index 2c41994f8..3bbd33497 100644
--- a/src/data/data1d/Spectrum1D/integrals/initiateIntegrals.ts
+++ b/src/data/data1d/Spectrum1D/integrals/initiateIntegrals.ts
@@ -3,21 +3,17 @@ import { Spectrum1D } from 'nmr-load-save';
import { Integrals, mapIntegrals } from 'nmr-processing';
export function initiateIntegrals(
- options: Partial<{ integrals: Integrals }>,
+ inputSpectrum: Partial,
spectrum: Spectrum1D,
+ options: Integrals['options'],
) {
return merge(
{
values: [],
- options: {
- sum: undefined,
- isSumConstant: true,
- sumAuto: true,
- },
+ options,
},
- options.integrals,
{
- values: mapIntegrals(options?.integrals?.values || [], spectrum),
+ values: mapIntegrals(inputSpectrum?.integrals?.values || [], spectrum),
},
);
}
diff --git a/src/data/data1d/Spectrum1D/peaks/initiatePeaks.ts b/src/data/data1d/Spectrum1D/peaks/initiatePeaks.ts
index 1df3022cf..f5c0e4303 100644
--- a/src/data/data1d/Spectrum1D/peaks/initiatePeaks.ts
+++ b/src/data/data1d/Spectrum1D/peaks/initiatePeaks.ts
@@ -1,12 +1,12 @@
import merge from 'lodash/merge';
import { Spectrum1D } from 'nmr-load-save';
-import { Peaks, mapPeaks } from 'nmr-processing';
+import { mapPeaks } from 'nmr-processing';
export function initiatePeaks(
- options: Partial<{ peaks: Peaks }>,
+ inputSpectrum: Partial,
spectrum: Spectrum1D,
) {
- return merge({ values: [], options: {} }, options.peaks, {
- values: mapPeaks(options?.peaks?.values || [], spectrum),
+ return merge({ values: [], options: {} }, inputSpectrum.peaks, {
+ values: mapPeaks(inputSpectrum?.peaks?.values || [], spectrum),
});
}
diff --git a/src/data/data1d/Spectrum1D/ranges/addRange.ts b/src/data/data1d/Spectrum1D/ranges/addRange.ts
index 0cfdd48c6..674ea0dd4 100644
--- a/src/data/data1d/Spectrum1D/ranges/addRange.ts
+++ b/src/data/data1d/Spectrum1D/ranges/addRange.ts
@@ -3,7 +3,7 @@ import { xyIntegration } from 'ml-spectra-processing';
import { Spectrum1D } from 'nmr-load-save';
import { Signal1D, mapRanges } from 'nmr-processing';
-import { DatumKind } from '../../../constants/SignalsKinds';
+import { DATUM_KIND } from '../../../constants/signalsKinds';
import detectSignal from './detectSignal';
@@ -24,7 +24,7 @@ export function createRangeObj({
to,
absolute, // the real value,
signals: [{ id: v4(), ...signal }],
- kind: DatumKind.signal,
+ kind: DATUM_KIND.signal,
integration: 0,
};
}
diff --git a/src/data/data1d/Spectrum1D/ranges/changeRange.ts b/src/data/data1d/Spectrum1D/ranges/changeRange.ts
index e09991c9e..df22f56dc 100644
--- a/src/data/data1d/Spectrum1D/ranges/changeRange.ts
+++ b/src/data/data1d/Spectrum1D/ranges/changeRange.ts
@@ -25,8 +25,8 @@ export function changeRange(spectrum: Spectrum1D, range: Range) {
if (index !== -1) {
spectrum.ranges.values[index] = {
...spectrum.ranges.values[index],
- originFrom: from,
- originTo: to,
+ originalFrom: from,
+ originalTo: to,
...range,
absolute,
signals: [
diff --git a/src/data/data1d/Spectrum1D/ranges/checkRangeKind.ts b/src/data/data1d/Spectrum1D/ranges/checkRangeKind.ts
index abfa20f7b..df18f8c77 100644
--- a/src/data/data1d/Spectrum1D/ranges/checkRangeKind.ts
+++ b/src/data/data1d/Spectrum1D/ranges/checkRangeKind.ts
@@ -1,8 +1,8 @@
import { Range } from 'nmr-processing';
-import { SignalKindsToInclude } from '../../../constants/SignalsKinds';
+import { SIGNAL_INLCUDED_KINDS } from '../../../constants/signalsKinds';
import { checkSignalKinds } from '../../../utilities/RangeUtilities';
export function checkRangeKind(range: Range): boolean {
- return range.signals && checkSignalKinds(range, SignalKindsToInclude);
+ return range.signals && checkSignalKinds(range, SIGNAL_INLCUDED_KINDS);
}
diff --git a/src/data/data1d/Spectrum1D/ranges/detectRange.ts b/src/data/data1d/Spectrum1D/ranges/detectRange.ts
index 2527bb2ac..243cad43d 100644
--- a/src/data/data1d/Spectrum1D/ranges/detectRange.ts
+++ b/src/data/data1d/Spectrum1D/ranges/detectRange.ts
@@ -25,8 +25,8 @@ export function detectRange(
return {
id: v4(),
- originFrom: from - shiftX,
- originTo: to - shiftX,
+ originalFrom: from - shiftX,
+ originalTo: to - shiftX,
from,
to,
absolute, // the real value,
diff --git a/src/data/data1d/Spectrum1D/ranges/detectSignal.ts b/src/data/data1d/Spectrum1D/ranges/detectSignal.ts
index 5cf663326..b0b3458b1 100644
--- a/src/data/data1d/Spectrum1D/ranges/detectSignal.ts
+++ b/src/data/data1d/Spectrum1D/ranges/detectSignal.ts
@@ -31,7 +31,7 @@ export default function detectSignal(
const result = analyseMultiplet(dataRoi, {
frequency,
- minimalResolution: 0.3,
+ minimalResolution: 0.1,
maxTestedJ: 17,
checkSymmetryFirst: true,
takeBestPartMultiplet: true,
diff --git a/src/data/data1d/Spectrum1D/ranges/initiateRanges.ts b/src/data/data1d/Spectrum1D/ranges/initiateRanges.ts
index 42d5cb25a..e31d084c1 100644
--- a/src/data/data1d/Spectrum1D/ranges/initiateRanges.ts
+++ b/src/data/data1d/Spectrum1D/ranges/initiateRanges.ts
@@ -3,21 +3,17 @@ import { Spectrum1D } from 'nmr-load-save';
import { Ranges, mapRanges } from 'nmr-processing';
export function initiateRanges(
- options: Partial<{ ranges: Ranges }>,
+ inputSpectrum: Partial,
spectrum: Spectrum1D,
+ options: Ranges['options'],
) {
return merge(
{
values: [],
- options: {
- sum: undefined,
- isSumConstant: true,
- sumAuto: true,
- },
+ options,
},
- options.ranges,
{
- values: mapRanges(options?.ranges?.values || [], spectrum),
+ values: mapRanges(inputSpectrum?.ranges?.values || [], spectrum),
},
);
}
diff --git a/src/data/data2d/Spectrum2D/getSlice.ts b/src/data/data2d/Spectrum2D/getSlice.ts
index 4bd46e976..f5e054a7b 100644
--- a/src/data/data2d/Spectrum2D/getSlice.ts
+++ b/src/data/data2d/Spectrum2D/getSlice.ts
@@ -19,6 +19,7 @@ export function getSlice(spectrum: Spectrum2D, position: SlicePosition) {
const data = info.isFid
? (spectraData as NmrData2DFid).re
: (spectraData as NmrData2DFt).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);
@@ -55,10 +56,10 @@ export function getSlice(spectrum: Spectrum2D, position: SlicePosition) {
re: new Float64Array(data.z.length),
};
- let index = data.z.length - 1;
for (let i = 0; i < data.z.length; i++) {
- dataY.re[i] += data.z[index--][xIndex];
+ dataY.re[i] += data.z[i][xIndex];
}
+
const horizontal = initiateDatum1D({ info: infoX, data: dataX });
const vertical = initiateDatum1D({ info: infoY, data: dataY });
return { horizontal, vertical };
diff --git a/src/data/data2d/Spectrum2D/zones/detectZones.ts b/src/data/data2d/Spectrum2D/zones/detectZones.ts
index 46f07cc49..2c35a459b 100644
--- a/src/data/data2d/Spectrum2D/zones/detectZones.ts
+++ b/src/data/data2d/Spectrum2D/zones/detectZones.ts
@@ -1,7 +1,6 @@
-import { Zone } from 'nmr-processing';
+import { Zone, mapZones } from 'nmr-processing';
import { DetectionZonesOptions, getDetectionZones } from './getDetectionZones';
-import { mapZones } from './mapZones';
export function detectZones(datum, options: DetectionZonesOptions): Zone[] {
const zones = getDetectionZones(datum, options);
diff --git a/src/data/data2d/Spectrum2D/zones/detectZonesManual.ts b/src/data/data2d/Spectrum2D/zones/detectZonesManual.ts
index 3c7ef41ca..a9ef37786 100644
--- a/src/data/data2d/Spectrum2D/zones/detectZonesManual.ts
+++ b/src/data/data2d/Spectrum2D/zones/detectZonesManual.ts
@@ -1,7 +1,6 @@
-import { Zone } from 'nmr-processing';
+import { Zone, mapZones } from 'nmr-processing';
import { DetectionZonesOptions, getDetectionZones } from './getDetectionZones';
-import { mapZones } from './mapZones';
/**
*
diff --git a/src/data/data2d/Spectrum2D/zones/initiateZones.ts b/src/data/data2d/Spectrum2D/zones/initiateZones.ts
index b64b519d4..85652bbba 100644
--- a/src/data/data2d/Spectrum2D/zones/initiateZones.ts
+++ b/src/data/data2d/Spectrum2D/zones/initiateZones.ts
@@ -1,8 +1,6 @@
import merge from 'lodash/merge';
import { Spectrum2D } from 'nmr-load-save';
-import { Zones } from 'nmr-processing';
-
-import { mapZones } from './mapZones';
+import { Zones, mapZones } from 'nmr-processing';
export function initiateZones(
options: Partial<{ zones: Zones }>,
diff --git a/src/data/data2d/Spectrum2D/zones/mapZones.ts b/src/data/data2d/Spectrum2D/zones/mapZones.ts
deleted file mode 100644
index dbe9c2351..000000000
--- a/src/data/data2d/Spectrum2D/zones/mapZones.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import { v4 } from '@lukeed/uuid';
-import { Spectrum2D } from 'nmr-load-save';
-import { Zone, Signal2D } from 'nmr-processing';
-
-import { DatumKind } from '../../../constants/SignalsKinds';
-import { MapOptions, ShiftTarget } from '../../../types/common/MapOptions';
-import { get2DSpectrumErrorValue } from '../get2DSpectrumErrorValue';
-import { getShift, Shift2D } from '../getShift';
-
-import { isZoneExists } from './isZoneExists';
-
-function getSignal(signal: Signal2D, shiftTarget: ShiftTarget, shift: Shift2D) {
- const { x, y } = signal;
-
- if (shiftTarget === 'origin') {
- return {
- ...signal,
- x: {
- ...x,
- originDelta: x.delta - shift.x,
- },
- y: {
- ...y,
- originDelta: y.delta - shift.y,
- },
- };
- } else {
- return {
- ...signal,
- x: {
- ...x,
- delta: x.originDelta + shift.x,
- },
- y: {
- ...y,
- delta: y.originDelta + shift.y,
- },
- };
- }
-}
-
-export function mapZones(
- zones: Zone[],
- datum: Spectrum2D,
- options: MapOptions = {},
-) {
- const { checkIsExisting = true, shiftTarget = 'origin' } = options;
- const shift = getShift(datum);
- const error = get2DSpectrumErrorValue(datum);
-
- let _zones: Zone[] = zones;
-
- if (checkIsExisting) {
- _zones = zones.filter((zone) => !isZoneExists(zone, datum, error));
- }
-
- return _zones.map((zone: Zone) => {
- const x = zone.x || { from: 0, to: 0 };
- const y = zone.y || { from: 0, to: 0 };
-
- const signals = zone.signals.map((signal) => {
- const { id, kind } = signal;
- return {
- ...getSignal(signal, shiftTarget, shift),
- id: id || v4(),
- kind: kind || 'signal',
- };
- });
-
- return {
- ...zone,
- id: zone.id || v4(),
- x: { from: x.from, to: x.to },
- y: { from: y.from, to: y.to },
- signals,
- kind: zone.kind || DatumKind.signal,
- };
- });
-}
diff --git a/src/data/data2d/Spectrum2D/zones/updateZones.ts b/src/data/data2d/Spectrum2D/zones/updateZones.ts
index 71774f722..242d991f5 100644
--- a/src/data/data2d/Spectrum2D/zones/updateZones.ts
+++ b/src/data/data2d/Spectrum2D/zones/updateZones.ts
@@ -1,7 +1,6 @@
+import { mapZones } from 'nmr-processing';
import { Spectrum2D } from 'nmr-load-save';
-import { mapZones } from './mapZones';
-
export function updateZones(spectrum: Spectrum2D) {
spectrum.zones.values = mapZones(spectrum.zones.values, spectrum, {
checkIsExisting: false,
diff --git a/src/data/types/common/SignalKind.ts b/src/data/types/common/SignalKind.ts
new file mode 100644
index 000000000..a920a1302
--- /dev/null
+++ b/src/data/types/common/SignalKind.ts
@@ -0,0 +1,11 @@
+export type SignalKind =
+ | 'undefined'
+ | 'signal'
+ | 'reference'
+ | 'impurity'
+ | 'standard'
+ | 'p1'
+ | 'p2'
+ | 'p3'
+ // eslint-disable-next-line @typescript-eslint/ban-types
+ | (string & {});
diff --git a/src/data/utilities/RangeUtilities.ts b/src/data/utilities/RangeUtilities.ts
index 05dc3cd0e..3796dad3a 100644
--- a/src/data/utilities/RangeUtilities.ts
+++ b/src/data/utilities/RangeUtilities.ts
@@ -1,7 +1,7 @@
import omit from 'lodash/omit';
import { Range, Signal1D } from 'nmr-processing';
-import { DatumKind } from '../constants/SignalsKinds';
+import { DATUM_KIND } from '../constants/signalsKinds';
export function getDiaIDs(range: Range): string[] {
return ([] as string[]).concat(
@@ -88,7 +88,7 @@ export function addDefaultSignal(range) {
}
export function checkRangeKind(range) {
- return range.kind === DatumKind.signal;
+ return range.kind === DATUM_KIND.signal;
}
export function checkSignalKinds(range, kinds) {
diff --git a/src/data/utilities/ZoneUtilities.ts b/src/data/utilities/ZoneUtilities.ts
index a527b07ae..d34482cb5 100644
--- a/src/data/utilities/ZoneUtilities.ts
+++ b/src/data/utilities/ZoneUtilities.ts
@@ -1,6 +1,6 @@
import { Zone } from 'nmr-processing';
-import { DatumKind } from '../constants/SignalsKinds';
+import { DATUM_KIND } from '../constants/signalsKinds';
export function getDiaIDs(zone: Zone, axis: string): string[] {
return ([] as string[]).concat(
@@ -39,7 +39,7 @@ export function resetDiaIDs(zone: Zone, axis: string) {
}
export function checkZoneKind(zone: Zone): boolean {
- return zone.kind === DatumKind.signal;
+ return zone.kind === DATUM_KIND.signal;
}
export function checkSignalKinds(zone: Zone, kinds: string[]): boolean {
diff --git a/src/demo/preflight.css b/src/demo/preflight.css
deleted file mode 100644
index 3bdbcb032..000000000
--- a/src/demo/preflight.css
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
-Adapted from:
-https://raw.githubusercontent.com/tailwindlabs/tailwindcss/c1d6174546f81dc6997833fa47ab3fe3f7cdc14d/src/plugins/css/preflight.css
-
-Changes:
-- Replace calls to `theme()` with the default value.
-*/
-
-/*
-MIT License
-
-Copyright (c) Adam Wathan
-Copyright (c) Jonathan Reinink
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-/**
- * Manually forked from SUIT CSS Base: https://github.com/suitcss/base
- * A thin layer on top of normalize.css that provides a starting point more
- * suitable for web applications.
- */
-
-/**
- * Removes the default spacing and border for appropriate elements.
- */
-
-blockquote,
-dl,
-dd,
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-hr,
-figure,
-p,
-pre {
- margin: 0;
-}
-
-button {
- background-color: transparent;
- background-image: none;
-}
-
-/**
- * Work around a Firefox/IE bug where the transparent `button` background
- * results in a loss of the default `button` focus styles.
- */
-
-button:focus {
- outline: 1px dotted;
- outline: 5px auto -webkit-focus-ring-color;
-}
-
-fieldset {
- margin: 0;
- padding: 0;
-}
-
-ol,
-ul {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-/**
- * Tailwind custom reset styles
- */
-
-/**
- * 1. Use the user's configured `sans` font-family (with Tailwind's default
- * sans-serif font stack as a fallback) as a sane default.
- * 2. Use Tailwind's default "normal" line-height so the user isn't forced
- * to override it to ensure consistency even when using the default theme.
- */
-
-html {
- font-family:
- ui-sans-serif,
- system-ui,
- -apple-system,
- BlinkMacSystemFont,
- 'Segoe UI',
- Roboto,
- 'Helvetica Neue',
- Arial,
- 'Noto Sans',
- sans-serif,
- 'Apple Color Emoji',
- 'Segoe UI Emoji',
- 'Segoe UI Symbol',
- 'Noto Color Emoji'; /* 1 */
- line-height: 1.5; /* 2 */
-}
-
-/**
- * 1. Prevent padding and border from affecting element width.
- *
- * We used to set this in the html element and inherit from
- * the parent element for everything else. This caused issues
- * in shadow-dom-enhanced elements like where the content
- * is wrapped by a div with box-sizing set to `content-box`.
- *
- * https://github.com/mozdevs/cssremedy/issues/4
- *
- *
- * 2. Allow adding a border to an element by just adding a border-width.
- *
- * By default, the way the browser specifies that an element should have no
- * border is by setting it's border-style to `none` in the user-agent
- * stylesheet.
- *
- * In order to easily add borders to elements by just setting the `border-width`
- * property, we change the default border-style for all elements to `solid`, and
- * use border-width to hide them instead. This way our `border` utilities only
- * need to set the `border-width` property instead of the entire `border`
- * shorthand, making our border utilities much more straightforward to compose.
- *
- * https://github.com/tailwindcss/tailwindcss/pull/116
- */
-
-*,
-::before,
-::after {
- box-sizing: border-box; /* 1 */
- border-width: 0; /* 2 */
- border-style: solid; /* 2 */
- border-color: currentColor; /* 2 */
-}
-
-/*
- * Ensure horizontal rules are visible by default
- */
-
-hr {
- border-top-width: 1px;
-}
-
-/**
- * Undo the `border-style: none` reset that Normalize applies to images so that
- * our `border-{width}` utilities have the expected effect.
- *
- * The Normalize reset is unnecessary for us since we default the border-width
- * to 0 on all elements.
- *
- * https://github.com/tailwindcss/tailwindcss/issues/362
- */
-
-img {
- border-style: solid;
-}
-
-textarea {
- resize: vertical;
-}
-
-input::placeholder,
-textarea::placeholder {
- color: #a0aec0;
-}
-
-button,
-[role='button'] {
- cursor: pointer;
-}
-
-table {
- border-collapse: collapse;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- font-size: inherit;
- font-weight: inherit;
-}
-
-/**
- * Reset links to optimize for opt-in styling instead of
- * opt-out.
- */
-
-a {
- color: inherit;
- text-decoration: inherit;
-}
-
-/**
- * Reset form element properties that are easy to forget to
- * style explicitly so you don't inadvertently introduce
- * styles that deviate from your design system. These styles
- * supplement a partial reset that is already applied by
- * normalize.css.
- */
-
-button,
-input,
-optgroup,
-select,
-textarea {
- padding: 0;
- line-height: inherit;
- color: inherit;
-}
-
-/**
- * Use the configured 'mono' font family for elements that
- * are expected to be rendered with a monospace font, falling
- * back to the system monospace stack if there is no configured
- * 'mono' font family.
- */
-
-pre,
-code,
-kbd,
-samp {
- font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
- 'Courier New', monospace;
-}
-
-/**
- * Make replaced elements `display: block` by default as that's
- * the behavior you want almost all of the time. Inspired by
- * CSS Remedy, with `svg` added as well.
- *
- * https://github.com/mozdevs/cssremedy/issues/14
- */
-
-img,
-svg,
-video,
-canvas,
-audio,
-iframe,
-embed,
-object {
- display: block;
- vertical-align: middle;
-}
-
-/**
- * Constrain images and videos to the parent width and preserve
- * their instrinsic aspect ratio.
- *
- * https://github.com/mozdevs/cssremedy/issues/14
- */
-
-img,
-video {
- max-width: 100%;
- height: auto;
-}
diff --git a/src/demo/samples.json b/src/demo/samples.json
index 99b86b36d..f6776906e 100644
--- a/src/demo/samples.json
+++ b/src/demo/samples.json
@@ -120,6 +120,10 @@
"file": "./data/nmriumFromSource.json",
"title": "Zip file as source with multiple spectra"
},
+ {
+ "file": "./data/nmredata/nmredata.json",
+ "title": "NMReDATA Menthol 1D"
+ },
{
"file": "./data/brukerFolders/brukerFolderWithoutExpno.json",
"title": "Bruker Directory without expno level"
diff --git a/src/index.tsx b/src/index.tsx
index a06c7224a..c4305ef4f 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -7,7 +7,9 @@ import Test from './demo/views/Test';
// Reset styles so they do not affect development of the React component.
import 'modern-normalize/modern-normalize.css';
-import './demo/preflight.css';
+import 'react-science/styles/preflight.css';
+import '@blueprintjs/core/lib/css/blueprint.css';
+import '@blueprintjs/icons/lib/css/blueprint-icons.css';
import './demo/index.css';
diff --git a/src/utils/clipboard/clipboard.ts b/src/utils/clipboard/clipboard.ts
index a4df1271c..a5a0912ef 100644
--- a/src/utils/clipboard/clipboard.ts
+++ b/src/utils/clipboard/clipboard.ts
@@ -1,3 +1,5 @@
+import type { ClipboardItemDataType } from 'clipboard-polyfill';
+
export function readText(): Promise {
return import('clipboard-polyfill').then((c) => c.readText());
}
@@ -22,7 +24,7 @@ export function write(data: ClipboardItemInterface[]): Promise {
}
export function newClipboardItem(
- items: Record>,
+ items: Record,
options?: ClipboardItemOptions,
): Promise {
return import('clipboard-polyfill').then(
diff --git a/src/utils/clipboard/clipboardHooks.ts b/src/utils/clipboard/clipboardHooks.ts
index 067f494e8..0d9ca7db8 100644
--- a/src/utils/clipboard/clipboardHooks.ts
+++ b/src/utils/clipboard/clipboardHooks.ts
@@ -199,9 +199,7 @@ export function useClipboard(): UseClipboardReturn {
async rawWriteWithType(data: string, type = 'text/plain') {
try {
const item = await newClipboardItem({
- [type]: new Promise((resolve) => {
- resolve(new Blob([data], { type }));
- }),
+ [type]: new Blob([data], { type }),
});
return await write([item]);
} catch {
diff --git a/src/utils/stringCapitalize.ts b/src/utils/stringCapitalize.ts
new file mode 100644
index 000000000..851b5883a
--- /dev/null
+++ b/src/utils/stringCapitalize.ts
@@ -0,0 +1,3 @@
+export function stringCapitalize(str: string) {
+ return str.charAt(0).toUpperCase() + str.slice(1);
+}
diff --git a/test-e2e/core/import.test.ts b/test-e2e/core/import.test.ts
index 211561642..09cdba103 100644
--- a/test-e2e/core/import.test.ts
+++ b/test-e2e/core/import.test.ts
@@ -44,7 +44,9 @@ test('should load and migrate .nmrium data from version 1 to version 2', async (
await test.step('check Peaks', async () => {
await nmrium.clickPanel('Peaks');
- const peaks = nmrium.page.locator('_react=PeakAnnotation');
+ const peaks = nmrium.page.locator(
+ '_react=Peaks[peaksSource="peaks"] >> _react=PeakAnnotation',
+ );
await expect(peaks).toHaveCount(6);
});
@@ -83,7 +85,9 @@ test('should load .nmrium data from version 3', async ({ page }) => {
await test.step('check Peaks', async () => {
await nmrium.clickPanel('Peaks');
- const peaks = nmrium.page.locator('_react=PeakAnnotation');
+ const peaks = nmrium.page.locator(
+ '_react=Peaks[peaksSource="peaks"] >> _react=PeakAnnotation',
+ );
await expect(peaks).toHaveCount(2);
});
diff --git a/test-e2e/panels/peaks.test.ts b/test-e2e/panels/peaks.test.ts
index 36323ac8d..6dfff1077 100644
--- a/test-e2e/panels/peaks.test.ts
+++ b/test-e2e/panels/peaks.test.ts
@@ -6,7 +6,9 @@ import NmriumPage from '../NmriumPage';
import { selectRange } from '../utilities/selectRange';
async function addPeaks(nmrium: NmriumPage) {
- const peakAnnotationLocator = nmrium.page.locator('_react=PeakAnnotation');
+ const peaksAnnotationLocator = nmrium.page.locator(
+ '_react=Peaks[peaksSource="peaks"] >> _react=PeakAnnotation',
+ );
// select peak picking tool
await nmrium.clickTool('peakPicking');
@@ -18,7 +20,7 @@ async function addPeaks(nmrium: NmriumPage) {
endX: 100,
});
- await expect(peakAnnotationLocator).toHaveCount(1);
+ await expect(peaksAnnotationLocator).toHaveCount(1);
// TODO: Get rid of this timeout.
// Without it, the click seems to have no effect.
@@ -32,12 +34,12 @@ async function addPeaks(nmrium: NmriumPage) {
},
});
- await expect(peakAnnotationLocator).toHaveCount(2);
+ await expect(peaksAnnotationLocator).toHaveCount(2);
}
async function shiftX(nmrium: NmriumPage) {
const peakLocator = nmrium.page.locator(
- '_react=PeakAnnotation >> nth=0 >> text',
+ '_react=Peaks[peaksSource="peaks"] >> _react=PeakAnnotation >> nth=0 >> text',
);
await peakLocator.click();
@@ -60,20 +62,24 @@ async function shiftSpectraByDeltaColumn(nmrium: NmriumPage) {
await inputLocator.press('Enter');
const peakInputLocator = nmrium.page.locator(
- '_react=PeakAnnotation >> nth=0 >>text',
+ '_react=Peaks[peaksSource="peaks"] >> _react=PeakAnnotation >> nth=0 >>text',
);
await expect(peakInputLocator).toHaveText('20.00');
}
async function deletePeak(nmrium: NmriumPage) {
const peakAnnotationLocator = nmrium.page.locator(
- '_react=PeakAnnotation >> nth=0',
+ '_react=Peaks[peaksSource="peaks"] >> _react=PeakAnnotation >> nth=0',
);
await peakAnnotationLocator.hover();
await nmrium.page.keyboard.press('Delete');
// Test that the peak deleted
- await expect(nmrium.page.locator('_react=PeakAnnotation')).toHaveCount(1);
+ await expect(
+ nmrium.page.locator(
+ '_react=Peaks[peaksSource="peaks"] >> _react=PeakAnnotation',
+ ),
+ ).toHaveCount(1);
}
test('add/shift/delete peaks', async ({ page }) => {
@@ -105,7 +111,11 @@ test('Automatic peak picking should work', async ({ page }) => {
//apply auto ranges detection
await nmrium.page.click('button >> text=Apply');
- await expect(nmrium.page.locator('_react=PeakAnnotation')).toHaveCount(50);
+ await expect(
+ nmrium.page.locator(
+ '_react=Peaks[peaksSource="peaks"] >> _react=PeakAnnotation',
+ ),
+ ).toHaveCount(50);
});
test('Processed spectra peaks', async ({ page }) => {
const nmrium = await NmriumPage.create(page);
diff --git a/test-e2e/panels/ranges.test.ts b/test-e2e/panels/ranges.test.ts
index b8b15101a..33e8476e1 100644
--- a/test-e2e/panels/ranges.test.ts
+++ b/test-e2e/panels/ranges.test.ts
@@ -134,6 +134,7 @@ test('Automatic ranges detection should work', async ({ page }) => {
await expect(range).toContainText(r);
}
});
+
test('Multiplicity should be visible', async ({ page }) => {
const nmrium = await NmriumPage.create(page);
await test.step('Open FULL ethylbenzene 2D spectrum', async () => {
@@ -192,6 +193,7 @@ test('Multiplicity should be visible', async ({ page }) => {
).toBeVisible();
});
});
+
test('Range state', async ({ page }) => {
const nmrium = await NmriumPage.create(page);
await test.step('Open FULL ethylbenzene 2D spectrum', async () => {
@@ -210,12 +212,18 @@ test('Range state', async ({ page }) => {
await nmrium.page.click('text=Auto ranges picking');
});
await test.step('Active range tools', async () => {
- // Check that the integrals btn is on
+ // Check that the peaks btn is off
await expect(
nmrium.page.locator(
- '_react=ToolTip[title="Hide integrals" i] >> .toggle-active',
+ '_react=RangesPanel >> _react=ToolTip[title="Show peaks" i] >> .toggle-active',
),
- ).toBeVisible();
+ ).toBeHidden();
+ // Check that the integrals btn is off
+ await expect(
+ nmrium.page.locator(
+ '_react=ToolTip[title="Show integrals" i] >> .toggle-active',
+ ),
+ ).toBeHidden();
// Check that the multiplicity tree btn is off
await expect(
nmrium.page.locator(
@@ -223,14 +231,23 @@ test('Range state', async ({ page }) => {
),
).toBeHidden();
- // Check range integral
- expect(
- await nmrium.page.locator('_react=RangeIntegral').count(),
- ).toBeGreaterThan(0);
+ // Check peaks within ranges are hidden
+ await expect(nmrium.page.locator('_react=PeakAnnotation')).toBeHidden();
+ // Check integrals within ranges are hidden
+ await expect(nmrium.page.locator('_react=RangeIntegral')).toBeHidden();
// Check multiplicity tree
await expect(nmrium.page.locator('_react=MultiplicityTree')).toBeHidden();
+ //show integrals
+ await nmrium.page.click(
+ '_react=RangesPanel >> _react=ToolTip[title="Show peaks" i] >> button',
+ );
+ //show integrals
+ await nmrium.page.click(
+ '_react=ToolTip[title="Show integrals" i] >> button',
+ );
+
//show multiplicity trees
await nmrium.page.click(
'_react=ToolTip[title="Show Multiplicity Trees in Spectrum" i] >> button',
@@ -241,6 +258,14 @@ test('Range state', async ({ page }) => {
'_react=ToolTip[title="Hide multiplicity trees in spectrum" i] >> .toggle-active',
),
).toBeVisible();
+ // Check peaks within ranges are visible
+ expect(
+ await nmrium.page.locator('_react=PeakAnnotation').count(),
+ ).toBeGreaterThan(0);
+ // Check integrals within ranges are visible
+ expect(
+ await nmrium.page.locator('_react=RangeIntegral').count(),
+ ).toBeGreaterThan(0);
// Check multiplicity tree is visible
expect(
await nmrium.page.locator('_react=MultiplicityTree').count(),
@@ -255,19 +280,27 @@ test('Range state', async ({ page }) => {
await nmrium.page.click(
'_react=SpectraTable >> _react=ReactTableRow >> nth=1',
);
- // Check that the integrals btn is on
+ // Check that the peaks btn is not active
await expect(
nmrium.page.locator(
- '_react=ToolTip[title="Hide integrals" i] >> .toggle-active',
+ '_react=RangesPanel >> _react=ToolTip[title="Hide peaks" i]',
),
).toBeVisible();
+ // Check that the integrals btn is not active
+ await expect(
+ nmrium.page.locator('_react=ToolTip[title="Hide integrals" i]'),
+ ).toBeVisible();
// Check that the multiplicity tree btn is on
await expect(
nmrium.page.locator(
- '_react=ToolTip[title="Hide multiplicity trees in spectrum" i] >> .toggle-active',
+ '_react=ToolTip[title="Hide multiplicity trees in spectrum" i]',
),
).toBeVisible();
+ // Check range peaks
+ expect(
+ await nmrium.page.locator('_react=PeakAnnotation').count(),
+ ).toBeGreaterThan(0);
// Check range integrals
expect(
await nmrium.page.locator('_react=RangeIntegral').count(),
@@ -278,6 +311,7 @@ test('Range state', async ({ page }) => {
).toBeGreaterThan(0);
});
});
+
test('Auto peak picking on all spectra', async ({ page }) => {
const nmrium = await NmriumPage.create(page);
await test.step('Open FULL ethylbenzene 2D spectrum', async () => {
@@ -309,7 +343,7 @@ test('Auto peak picking on all spectra', async ({ page }) => {
await nmrium.clickPanel('Ranges');
await expect(nmrium.page.getByTestId('range')).toHaveCount(16);
await expect(
- nmrium.page.locator('_react=RangesTablePanel >> _react=PanelHeader'),
+ nmrium.page.locator('_react=RangesPanel >> _react=PanelHeader'),
).toContainText('[ 16 ]');
});
@@ -318,7 +352,7 @@ test('Auto peak picking on all spectra', async ({ page }) => {
await nmrium.page.click('_react=SpectrumsTabs >> _react=Tab[tabid="13C"]');
await expect(nmrium.page.getByTestId('range')).toHaveCount(15);
await expect(
- nmrium.page.locator('_react=RangesTablePanel >> _react=PanelHeader'),
+ nmrium.page.locator('_react=RangesPanel >> _react=PanelHeader'),
).toContainText('[ 15 ]');
});
@@ -354,3 +388,96 @@ test('Auto peak picking on all spectra', async ({ page }) => {
).toContainText('[ 44 ]');
});
});
+
+test('2D spectra reference change', async ({ page }) => {
+ const xAxisDefault = [1, 2, 3, 4, 5, 6, 7, 8];
+ const yAxisDefault = [0, 20, 40, 60, 80, 100, 120, 140, 160];
+ const nmrium = await NmriumPage.create(page);
+ await test.step('Open 2D spectrum', async () => {
+ await nmrium.page.click('li >> text=Cytisine');
+ await nmrium.page.click('li >> text=HSQC cytisine + 1D spectra');
+ await expect(nmrium.page.locator('#nmrSVG')).toBeVisible();
+ await expect(nmrium.page.locator('.x')).toContainText(
+ xAxisDefault.join(''),
+ );
+ await expect(nmrium.page.locator('.y')).toContainText(
+ yAxisDefault.join(''),
+ );
+ });
+
+ await test.step('Auto zone picking', async () => {
+ await nmrium.clickTool('zonePicking');
+ await nmrium.page.click('text=Auto Zones Picking');
+ });
+
+ await test.step("Check spectrum's zones", async () => {
+ await expect(nmrium.page.locator('.zone')).toHaveCount(15);
+ await expect(
+ nmrium.page.locator('_react=ZonesPanel >> _react=PanelHeader'),
+ ).toContainText('[ 15 ]');
+
+ const x = 2.9139017520509753;
+ const y = 35.65263186073236;
+ await expect(
+ nmrium.page.locator(
+ '_react=ZonesPanel >> _react=ZonesTableRow >> nth=0 >> td >> nth=1',
+ ),
+ ).toHaveText(x.toFixed(2));
+ await expect(
+ nmrium.page.locator(
+ '_react=ZonesPanel >> _react=ZonesTableRow >> nth=0 >> td >> nth=2',
+ ),
+ ).toHaveText(y.toFixed(2));
+
+ await expect(
+ nmrium.page.locator(
+ `_react=Signal[signal.x.delta=${x}][signal.y.delta=${y}]`,
+ ),
+ ).toBeVisible();
+ });
+ await test.step('Change reference', async () => {
+ const x = 1000;
+ const y = 2000;
+ await nmrium.page
+ .locator(
+ '_react=ZonesPanel >> _react=ZonesTableRow >> nth=0 >> td >> nth=1',
+ )
+ .dblclick();
+
+ await nmrium.page.keyboard.type(x.toString());
+ await nmrium.page.keyboard.press('Enter');
+
+ await nmrium.page
+ .locator(
+ '_react=ZonesPanel >> _react=ZonesTableRow >> nth=0 >> td >> nth=2',
+ )
+ .dblclick();
+
+ await nmrium.page.keyboard.type(y.toString());
+ await nmrium.page.keyboard.press('Enter');
+
+ await expect(
+ nmrium.page.locator(
+ '_react=ZonesPanel >> _react=ZonesTableRow >> nth=0 >> td >> nth=1',
+ ),
+ ).toHaveText(x.toFixed(2));
+ await expect(
+ nmrium.page.locator(
+ '_react=ZonesPanel >> _react=ZonesTableRow >> nth=0 >> td >> nth=2',
+ ),
+ ).toHaveText(y.toFixed(2));
+
+ await expect(
+ nmrium.page.locator(
+ `_react=Signal[signal.x.delta=${x}][signal.y.delta=${y}]`,
+ ),
+ ).toBeVisible();
+
+ const xShift = 997;
+ const yShift = 1960;
+ const newXAxis = xAxisDefault.map((n) => n + xShift);
+ const newYAxis = yAxisDefault.map((n) => n + yShift);
+ await expect(nmrium.page.locator('.x')).toContainText(newXAxis.join(''));
+ await expect(nmrium.page.locator('.y')).toContainText(newYAxis.join(''));
+ });
+});
diff --git a/test-e2e/panels/structures.test.ts b/test-e2e/panels/structures.test.ts
index f84eff7f0..5ab204b32 100644
--- a/test-e2e/panels/structures.test.ts
+++ b/test-e2e/panels/structures.test.ts
@@ -310,7 +310,7 @@ test('molecules 1H spectrum', async ({ page, browserName }) => {
await test.step('Check molecules in ranges', async () => {
await nmrium.clickPanel('Ranges');
await nmrium.page
- .locator('_react=ButtonToolTip[popupTitle="Change ranges sum"]')
+ .locator('_react=ButtonToolTip[popupTitle*="Change ranges sum" i]')
.click();
await expect(nmrium.page.locator('_react=Modal >> #molSVG0')).toBeVisible();
await expect(
diff --git a/tsconfig.cjs.json b/tsconfig.cjs.json
deleted file mode 100644
index 9e585759e..000000000
--- a/tsconfig.cjs.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "./tsconfig.esm.json",
- "compilerOptions": {
- "outDir": "lib-cjs",
- "noEmit": false,
- "module": "CommonJS",
- "declaration": false
- }
-}
diff --git a/tsconfig.json b/tsconfig.json
index 1a8b68251..a0ddff7d9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -11,8 +11,8 @@
"noImplicitAny": false,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
- "module": "esnext",
- "moduleResolution": "Node16",
+ "moduleResolution": "Bundler",
+ "module": "ES2022",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,