diff --git a/dist/actions/threshold.js b/dist/actions/threshold.js
index 3feeeee2..5359753b 100644
--- a/dist/actions/threshold.js
+++ b/dist/actions/threshold.js
@@ -10,9 +10,9 @@ const updateThresholdValue = payload => ({
payload
});
exports.updateThresholdValue = updateThresholdValue;
-const resetThresholdValue = () => ({
+const resetThresholdValue = (payload = false) => ({
type: _action_type.THRESHOLD.RESET_VALUE,
- payload: false
+ payload
});
exports.resetThresholdValue = resetThresholdValue;
const toggleThresholdIsEdit = payload => ({
diff --git a/dist/actions/ui.js b/dist/actions/ui.js
index 590f7b16..88a2ab61 100644
--- a/dist/actions/ui.js
+++ b/dist/actions/ui.js
@@ -3,7 +3,7 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
-exports.setUiViewerType = exports.setUiSweepType = exports.selectUiSweep = exports.scrollUiWheel = exports.displaySubViewerAt = exports.clickUiTarget = void 0;
+exports.setUiViewerType = exports.setUiSweepType = exports.selectUiSweep = exports.scrollUiWheel = exports.restoreSweepExtent = exports.displaySubViewerAt = exports.clickUiTarget = void 0;
var _action_type = require("../constants/action_type");
var _list_ui = require("../constants/list_ui");
var _integration_draft = require("../helpers/integration_draft.js");
@@ -45,15 +45,25 @@ const scrollUiWheel = payload => ({
payload
});
exports.scrollUiWheel = scrollUiWheel;
-const clickUiTarget = (payload, onPeak, voltammetryPeakIdx = 0, jcampIdx = 0, onPecker = false, sourceHint = null) => ({
- type: _action_type.UI.CLICK_TARGET,
- payload,
- onPeak,
- voltammetryPeakIdx,
- jcampIdx,
- onPecker,
- sourceHint
+const restoreSweepExtent = payload => ({
+ type: _action_type.UI.SWEEP.SELECT_ZOOMIN,
+ payload
});
+exports.restoreSweepExtent = restoreSweepExtent;
+const clickUiTarget = (payload, onPeak, voltammetryPeakIdx, jcampIdx, onPecker, sourceHint) => {
+ const action = {
+ type: _action_type.UI.CLICK_TARGET,
+ payload,
+ onPeak,
+ voltammetryPeakIdx: voltammetryPeakIdx ?? 0,
+ onPecker: onPecker ?? false,
+ sourceHint: sourceHint ?? null
+ };
+ if (Number.isFinite(jcampIdx)) {
+ action.jcampIdx = jcampIdx;
+ }
+ return action;
+};
exports.clickUiTarget = clickUiTarget;
const displaySubViewerAt = payload => ({
type: _action_type.UI.SUB_VIEWER.DISPLAY_VIEWER_AT,
diff --git a/dist/app.js b/dist/app.js
index d66e1117..4c4217b1 100644
--- a/dist/app.js
+++ b/dist/app.js
@@ -72,6 +72,8 @@ const SpectraEditor = ({
multiMolSvgs,
entityFileNames,
userManualLink,
+ curveIdx,
+ sweepExtent,
onLcmsPageRequest
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactRedux.Provider, {
store: store,
@@ -80,6 +82,8 @@ const SpectraEditor = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_layer_init.default, {
entity: entity,
multiEntities: multiEntities,
+ curveIdx: curveIdx,
+ sweepExtent: sweepExtent,
entityFileNames: entityFileNames,
userManualLink: userManualLink,
others: others,
@@ -103,6 +107,8 @@ exports.SpectraEditor = SpectraEditor;
SpectraEditor.propTypes = {
entity: _propTypes.default.object.isRequired,
multiEntities: _propTypes.default.array,
+ curveIdx: _propTypes.default.number,
+ sweepExtent: _propTypes.default.object,
entityFileNames: _propTypes.default.array,
others: _propTypes.default.object,
cLabel: _propTypes.default.string,
diff --git a/dist/components/cmd_bar/01_viewer.js b/dist/components/cmd_bar/01_viewer.js
index 87093240..c7c6adb0 100644
--- a/dist/components/cmd_bar/01_viewer.js
+++ b/dist/components/cmd_bar/01_viewer.js
@@ -49,19 +49,16 @@ const Viewer = ({
})
})
})
- }), hideCmdAnaViewerSt ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
+ }), hideCmdAnaViewerSt || disableCmdAnaViewerSt ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
title: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: "txt-sv-tp",
children: "Analysis Viewer"
}),
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
- className: (0, _classnames.default)((0, _common.focusStyle)(isfocusAnalysisSt, classes), 'btn-sv-bar-analysis'),
- disabled: disableCmdAnaViewerSt,
- onClick: onViewAnalysis,
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpellcheckOutlined.default, {
- className: classes.icon
- })
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
+ className: (0, _classnames.default)((0, _common.focusStyle)(isfocusAnalysisSt, classes), 'btn-sv-bar-analysis'),
+ onClick: onViewAnalysis,
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpellcheckOutlined.default, {
+ className: classes.icon
})
})
})]
diff --git a/dist/components/cmd_bar/03_peak.js b/dist/components/cmd_bar/03_peak.js
index 4aeadb6c..a15b2862 100644
--- a/dist/components/cmd_bar/03_peak.js
+++ b/dist/components/cmd_bar/03_peak.js
@@ -65,6 +65,13 @@ const Peak = ({
});
}
};
+ const showAddPeak = !disableAddPeakSt;
+ const showRmPeak = !disableRmPeakSt;
+ const showSetRef = !disableSetRefSt;
+ const showClearAll = !disableRmPeakSt;
+ if (!showAddPeak && !showRmPeak && !showSetRef && !showClearAll) {
+ return null;
+ }
if (isHandleMaxAndMinPeaksSt) {
const {
spectraList
@@ -87,7 +94,7 @@ const Peak = ({
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
className: classes.group,
"data-testid": "Peak",
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
+ children: [showAddPeak ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
title: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: "txt-sv-tp",
children: "Add Peak"
@@ -95,7 +102,6 @@ const Peak = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)((0, _common.focusStyle)(isFocusAddPeakSt, classes), 'btn-sv-bar-addpeak'),
- disabled: disableAddPeakSt,
onClick: onSweepPeakAdd,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-addpeak'),
@@ -103,7 +109,7 @@ const Peak = ({
})
})
})
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
+ }) : null, showRmPeak ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
title: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: "txt-sv-tp",
children: "Remove Peak"
@@ -111,20 +117,19 @@ const Peak = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)((0, _common.focusStyle)(isFocusRmPeakSt, classes), 'btn-sv-bar-rmpeak'),
- disabled: disableRmPeakSt,
- onClick: onSweepPeakDelete,
+ onClick: onSweepPeakDELETE,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-rmpeak'),
children: "P-"
})
})
})
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_tri_btn.default, {
+ }) : null, showClearAll ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_tri_btn.default, {
content: {
tp: 'Clear All Peaks'
},
cb: onClearAll,
- isClearAllDisabled: disableRmPeakSt,
+ isClearAllDisabled: false,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-rmallpeaks'),
children: "P"
@@ -132,7 +137,7 @@ const Peak = ({
className: (0, _classnames.default)(classes.txt, classes.txtIcon, 'txt-sv-bar-rmallpeaks'),
children: "x"
})]
- }), !disableSetRefSt ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
+ }) : null, showSetRef ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
title: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: "txt-sv-tp",
children: "Set Reference"
@@ -140,7 +145,6 @@ const Peak = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)((0, _common.focusStyle)(isFocusSetRefSt, classes), 'btn-sv-bar-setref'),
- disabled: disableSetRefSt,
onClick: onSweepAnchorShift,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_AddLocationOutlined.default, {
className: classes.icon
diff --git a/dist/components/cmd_bar/04_integration.js b/dist/components/cmd_bar/04_integration.js
index 7a61beb7..e4408c36 100644
--- a/dist/components/cmd_bar/04_integration.js
+++ b/dist/components/cmd_bar/04_integration.js
@@ -46,7 +46,7 @@ const styles = () => Object.assign({
}
}, _common.commonStyle);
const iconSize = '16px';
-const setFactor = (classes, isDisable, integrationSt, setIntegrationFkrAct, curveIdx) => {
+const setFactor = (classes, integrationSt, setIntegrationFkrAct, curveIdx) => {
const onFactorChanged = e => {
e.target.blur();
setIntegrationFkrAct({
@@ -72,7 +72,6 @@ const setFactor = (classes, isDisable, integrationSt, setIntegrationFkrAct, curv
}
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextField.default, {
className: classes.field,
- disabled: isDisable,
id: "intg-factor-name",
type: "number",
value: refFactor,
@@ -146,6 +145,9 @@ const Integration = ({
}
setUiSweepTypeAct(_list_ui.LIST_UI_SWEEP_TYPE.INTEGRATION_VISUAL_SPLIT, curveIdx);
};
+ if (isDisableSt) {
+ return null;
+ }
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
className: classes.group,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
@@ -156,12 +158,11 @@ const Integration = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_common.MuButton, {
className: (0, _classnames.default)(isFocusAddIntgSt ? classes.cancelBtn : (0, _common.focusStyle)(false, classes), 'btn-add-inter'),
- disabled: isDisableSt,
onClick: onSweepIntegtAdd,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.default, {
path: isFocusAddIntgSt ? _js.mdiClose : _js.mdiMathIntegral,
size: iconSize,
- color: isFocusAddIntgSt ? '#d32f2f' : iconColor(isDisableSt),
+ color: iconColor(isFocusAddIntgSt),
className: (0, _classnames.default)(classes.iconMdi, 'icon-sv-bar-addint')
}), isFocusAddIntgSt ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, classes.txtIcon, 'txt-sv-bar-addint'),
@@ -177,12 +178,11 @@ const Integration = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_common.MuButton, {
className: (0, _classnames.default)((0, _common.focusStyle)(isFocusRmIntgSt, classes), 'btn-remove-inter'),
- disabled: isDisableSt,
onClick: onSweepIntegtRm,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.default, {
path: _js.mdiMathIntegral,
size: iconSize,
- color: iconColor(isFocusRmIntgSt || isDisableSt),
+ color: iconColor(isFocusRmIntgSt),
className: (0, _classnames.default)(classes.iconMdi, 'icon-sv-bar-rmint')
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, classes.txtIcon, 'txt-sv-bar-rmint'),
@@ -190,7 +190,7 @@ const Integration = ({
})]
})
})
- }), ignoreRef ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
title: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: "txt-sv-tp",
children: "Set Integration Reference"
@@ -198,12 +198,11 @@ const Integration = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)((0, _common.focusStyle)(isFocusSetRefSt, classes), 'btn-set-inter-ref'),
- disabled: isDisableSt,
onClick: onSweepIntegtSR,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.default, {
path: _js.mdiReflectVertical,
size: iconSize,
- color: iconColor(isFocusSetRefSt || isDisableSt),
+ color: iconColor(isFocusSetRefSt),
className: (0, _classnames.default)(classes.iconMdi, 'icon-sv-bar-refint')
})
})
@@ -217,12 +216,11 @@ const Integration = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_common.MuButton, {
className: (0, _classnames.default)(isFocusSplitIntgSt ? classes.cancelBtn : (0, _common.focusStyle)(false, classes), 'btn-split-inter'),
- disabled: isDisableSt,
onClick: onSweepIntegtSplit,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.default, {
path: isFocusSplitIntgSt ? _js.mdiClose : _js.mdiMathIntegral,
size: iconSize,
- color: isFocusSplitIntgSt ? '#d32f2f' : iconColor(isDisableSt),
+ color: isFocusSplitIntgSt ? '#d32f2f' : iconColor(false),
className: (0, _classnames.default)(classes.iconMdi, 'icon-sv-bar-splitint')
}), isFocusSplitIntgSt ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, classes.txtIcon, 'txt-sv-bar-splitint'),
@@ -238,12 +236,11 @@ const Integration = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_common.MuButton, {
className: (0, _classnames.default)(isFocusVisualSplitIntgSt ? classes.cancelBtn : (0, _common.focusStyle)(false, classes), 'btn-visual-split-inter'),
- disabled: isDisableSt,
onClick: onSweepIntegtVisualSplit,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.default, {
path: isFocusVisualSplitIntgSt ? _js.mdiClose : _js.mdiMathIntegral,
size: iconSize,
- color: isFocusVisualSplitIntgSt ? '#d32f2f' : iconColor(isDisableSt),
+ color: isFocusVisualSplitIntgSt ? '#d32f2f' : iconColor(false),
className: (0, _classnames.default)(classes.iconMdi, 'icon-sv-bar-visualsplitint')
}), isFocusVisualSplitIntgSt ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, classes.txtIcon, 'txt-sv-bar-visualsplitint'),
@@ -252,7 +249,7 @@ const Integration = ({
})
})
})]
- }) : null, !ignoreRef ? setFactor(classes, isDisableSt, integrationSt, setIntegrationFkrAct, curveIdx) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_tri_btn.default, {
+ }) : null, !ignoreRef ? setFactor(classes, integrationSt, setIntegrationFkrAct, curveIdx) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_tri_btn.default, {
content: {
tp: 'Clear All Integration'
},
@@ -260,7 +257,7 @@ const Integration = ({
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.default, {
path: _js.mdiMathIntegral,
size: iconSize,
- color: iconColor(isDisableSt),
+ color: iconColor(false),
className: (0, _classnames.default)(classes.iconMdi, 'icon-sv-bar-rmallint')
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, classes.txtIcon, 'txt-sv-bar-rmallint'),
diff --git a/dist/components/cmd_bar/05_multiplicity.js b/dist/components/cmd_bar/05_multiplicity.js
index c725320e..223e38aa 100644
--- a/dist/components/cmd_bar/05_multiplicity.js
+++ b/dist/components/cmd_bar/05_multiplicity.js
@@ -29,10 +29,8 @@ const Multiplicity = ({
isFocusAddMpySt,
disableAddMpySt,
isFocusRmMpySt,
- disableRmMpySt,
isFocusAddPeakSt,
isFocusRmPeakSt,
- disableMpyPeakSt,
setUiSweepTypeAct,
clearMpyAllAct,
curveSt
@@ -47,6 +45,9 @@ const Multiplicity = ({
const onClearAll = () => clearMpyAllAct({
curveIdx
});
+ if (disableAddMpySt) {
+ return null;
+ }
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
className: classes.group,
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
@@ -57,7 +58,6 @@ const Multiplicity = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)((0, _common.focusStyle)(isFocusAddMpySt, classes), 'btn-sv-bar-addmpy'),
- disabled: disableAddMpySt,
onClick: onSweepMutAdd,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-addmpy'),
@@ -73,7 +73,6 @@ const Multiplicity = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)((0, _common.focusStyle)(isFocusRmMpySt, classes), 'btn-sv-bar-rmmpy'),
- disabled: disableRmMpySt,
onClick: onOneMutAdd,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-rmmpy'),
@@ -89,7 +88,6 @@ const Multiplicity = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)((0, _common.focusStyle)(isFocusAddPeakSt, classes), 'btn-sv-bar-addpeakmpy'),
- disabled: disableMpyPeakSt,
onClick: onPeakMutAdd,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-addpeakmpy'),
@@ -105,7 +103,6 @@ const Multiplicity = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)((0, _common.focusStyle)(isFocusRmPeakSt, classes), 'btn-sv-bar-rmpeakmpy'),
- disabled: disableMpyPeakSt,
onClick: onPeakMutRm,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-rmpeakmpy'),
@@ -113,14 +110,12 @@ const Multiplicity = ({
})
})
})
- }), disableAddMpySt ? null :
- /*#__PURE__*/
- // eslint-disable-line
- (0, _jsxRuntime.jsx)(_tri_btn.default, {
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_tri_btn.default, {
content: {
tp: 'Clear All Multiplicity'
},
cb: onClearAll,
+ isClearAllDisabled: false,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.txt, 'txt-sv-bar-rmallmpy'),
children: "Jx"
diff --git a/dist/components/cmd_bar/07_pecker.js b/dist/components/cmd_bar/07_pecker.js
index d8fbf678..d19d4e9f 100644
--- a/dist/components/cmd_bar/07_pecker.js
+++ b/dist/components/cmd_bar/07_pecker.js
@@ -110,7 +110,11 @@ const Pecker = ({
} = spectra;
hasRefPeaks = hasRefPeak;
}
- return !_cfg.default.hidePanelCyclicVolta(layoutSt) ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
+ if (_cfg.default.hidePanelCyclicVolta(layoutSt)) {
+ return null;
+ }
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
+ className: classes.group,
"data-testid": "Pecker",
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
title: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
@@ -161,7 +165,7 @@ const Pecker = ({
})
})
})]
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {});
+ });
};
const mapStateToProps = (state, _) => (
// eslint-disable-line
diff --git a/dist/components/cmd_bar/index.js b/dist/components/cmd_bar/index.js
index e82cf604..260e9bd1 100644
--- a/dist/components/cmd_bar/index.js
+++ b/dist/components/cmd_bar/index.js
@@ -26,6 +26,7 @@ var _r08_change_axes = _interopRequireDefault(require("./r08_change_axes"));
var _r09_detector = _interopRequireDefault(require("./r09_detector"));
var _r10_cv_density = _interopRequireDefault(require("./r10_cv_density"));
var _format = _interopRequireDefault(require("../../helpers/format"));
+var _cfg = _interopRequireDefault(require("../../helpers/cfg"));
var _jsxRuntime = require("react/jsx-runtime");
/* eslint-disable prefer-object-spread, function-paren-newline,
react/function-component-definition, react/require-default-props */
@@ -77,6 +78,8 @@ const CmdBar = ({
prependLcMsToolbar
}) => {
const isCvLayout = _format.default.isCyclicVoltaLayout(layoutSt);
+ const hideIntegration = isCvLayout || _cfg.default.btnCmdIntg(layoutSt);
+ const hideMultiplicity = isCvLayout || _cfg.default.btnCmdMpy(layoutSt);
const rightCluster = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_r01_layout.default, {
feature: feature,
@@ -118,7 +121,7 @@ const CmdBar = ({
feature: feature
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_pecker.default, {
jcampIdx: jcampIdx
- }), isCvLayout ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_integration.default, {}), isCvLayout ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_multiplicity.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_undo_redo.default, {})]
+ }), hideIntegration ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_integration.default, {}), hideMultiplicity ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_multiplicity.default, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_undo_redo.default, {})]
}), rightCluster]
});
};
diff --git a/dist/components/cmd_bar/r03_threshold.js b/dist/components/cmd_bar/r03_threshold.js
index 0ca008d9..c1016f8d 100644
--- a/dist/components/cmd_bar/r03_threshold.js
+++ b/dist/components/cmd_bar/r03_threshold.js
@@ -109,6 +109,16 @@ const Threshold = ({
} else {
thresVal = thresValSt || (feature ? feature.thresRef : hplcMsSt?.threshold?.value);
}
+ const {
+ curveIdx
+ } = curveSt;
+ const onResetThreshold = () => resetThresholdValueAct({
+ value: false,
+ curveIdx
+ });
+ const onToggleThreshold = () => toggleThresholdIsEditAct({
+ curveIdx
+ });
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
className: classes.groupRight,
children: [setThreshold(classes, thresVal, updateThresholdValueAct, curveSt), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Tooltip, {
@@ -120,7 +130,7 @@ const Threshold = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)('btn-sv-bar-thresref'),
disabled: _cfg.default.btnCmdThres(thresVal),
- onClick: resetThresholdValueAct,
+ onClick: onResetThreshold,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_RefreshOutlined.default, {
className: classes.icon
})
@@ -135,7 +145,7 @@ const Threshold = ({
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
className: (0, _classnames.default)('btn-sv-bar-thresrst'),
disabled: _cfg.default.btnCmdThres(thresVal),
- onClick: toggleThresholdIsEditAct,
+ onClick: onToggleThreshold,
children: restoreIcon(classes, hasEdit, isEditSt)
})
})
diff --git a/dist/components/cmd_bar/r05_submit_btn.js b/dist/components/cmd_bar/r05_submit_btn.js
index ceb5ca36..d198f6da 100644
--- a/dist/components/cmd_bar/r05_submit_btn.js
+++ b/dist/components/cmd_bar/r05_submit_btn.js
@@ -17,6 +17,7 @@ var _chem = require("../../helpers/chem");
var _common = require("./common");
var _extractPeaksEdit = require("../../helpers/extractPeaksEdit");
var _format = _interopRequireDefault(require("../../helpers/format"));
+var _shift = require("../../helpers/shift");
var _jsxRuntime = require("react/jsx-runtime");
/* eslint-disable prefer-object-spread, function-paren-newline,
react/function-component-definition, function-call-argument-newline,
@@ -89,7 +90,19 @@ const resolveLcmsIntegrationsExportForSubmit = (analysis, hplcMsSt) => {
}
return 'percent';
};
-const pickFromList = (list, index, fallback = null) => Array.isArray(list) && list[index] !== undefined ? list[index] : fallback;
+const emptyIntegration = {
+ stack: [],
+ refArea: 1,
+ refFactor: 1,
+ shift: 0,
+ edited: false
+};
+const emptyMultiplicity = {
+ stack: [],
+ shift: 0,
+ smExtext: false,
+ edited: false
+};
const hasBoolean = value => typeof value === 'boolean';
const resolveOptionalBooleanFlags = analysis => {
const flags = {};
@@ -124,9 +137,9 @@ const buildSpectrumPayload = ({
const peaksEdit = (0, _extractPeaksEdit.extractPeaksEdit)(feature, editPeakAtIndex, threshold, shiftSt, layoutSt, curveIdx);
const scan = (0, _chem.Convert2Scan)(feature, scanSt);
const thres = (0, _chem.Convert2Thres)(feature, threshold);
- const shift = pickFromList(shiftSt?.shifts, curveIdx, shiftSt);
- const integration = pickFromList(integrationSt?.integrations, curveIdx, integrationSt);
- const multiplicity = pickFromList(multiplicitySt?.multiplicities, curveIdx, multiplicitySt);
+ const shift = (0, _shift.shiftEntryAtIndex)(shiftSt, curveIdx);
+ const integration = (0, _shift.listEntryAtIndex)(integrationSt?.integrations, curveIdx, emptyIntegration);
+ const multiplicity = (0, _shift.listEntryAtIndex)(multiplicitySt?.multiplicities, curveIdx, emptyMultiplicity);
const {
xLabel,
yLabel
@@ -149,6 +162,7 @@ const buildSpectrumPayload = ({
return {
peaks: peaksEdit,
layout: layoutSt,
+ xUnit: xLabel,
shift,
scan,
thres,
@@ -166,10 +180,11 @@ const buildSpectrumPayload = ({
axesUnitsSt,
detectorSt,
dscMetaData,
+ feature,
...optionalBooleanFlags
};
};
-const onClickCb = (operationValue, isAscend, isIntensity, layoutSt, shiftSt, analysis, decimalSt, integrationSt, multiplicitySt, waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt, dscMetaData, curveList, editPeakSt, thresList, scanSt, feature, hplcMsSt) => () => {
+const onClickCb = (operationValue, isAscend, isIntensity, layoutSt, shiftSt, analysis, decimalSt, integrationSt, multiplicitySt, waveLengthSt, cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt, dscMetaData, curveList, editPeakSt, thresList, scanSt, feature, hplcMsSt, sweepExtentSt) => () => {
const defaultCurves = feature ? [{
feature
}] : [];
@@ -226,7 +241,10 @@ const onClickCb = (operationValue, isAscend, isIntensity, layoutSt, shiftSt, ana
}
return spectrumPayload;
});
+ const selectedIdx = Number.isFinite(curveSt?.curveIdx) ? curveSt.curveIdx : 0;
+ const selectedSpectrumPayload = spectraList[selectedIdx] || spectraList[0] || {};
const payload = {
+ ...selectedSpectrumPayload,
spectra_list: spectraList
};
if (lcmsGlobalFields) {
@@ -237,6 +255,9 @@ const onClickCb = (operationValue, isAscend, isIntensity, layoutSt, shiftSt, ana
curveIdx: curveSt.curveIdx
};
}
+ if (sweepExtentSt?.xExtent || sweepExtentSt?.yExtent) {
+ payload.sweepExtent = sweepExtentSt;
+ }
operationValue(payload);
};
const BtnSubmit = ({
@@ -261,7 +282,11 @@ const BtnSubmit = ({
axesUnitsSt,
detectorSt,
metaSt,
- hplcMsSt
+ hplcMsSt,
+ sweepExtentSt,
+ disabled,
+ className,
+ children
}) => {
// const disBtn = peaksEdit.length === 0 || statusSt.btnSubmit || disabled;
const {
@@ -290,13 +315,14 @@ const BtnSubmit = ({
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
title: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: "txt-sv-tp",
- children: "Submit"
+ children: operation.name || 'Submit'
}),
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_common.MuButton, {
- className: (0, _classnames.default)('btn-sv-bar-submit'),
+ className: (0, _classnames.default)('btn-sv-bar-submit', className),
color: "primary",
- onClick: onClickCb(operation.value, isAscend, isIntensity, layoutSt, shiftSt, forecastSt.predictions, decimalSt, integrationSt, multiplicitySt, waveLengthSt, cyclicvoltaPayload, curveSt, axesUnitsSt, detectorSt, dscMetaData, curveList, editPeakSt, thresList, scanSt, feature, hplcMsSt),
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_PlayCircleOutline.default, {
+ disabled: disabled,
+ onClick: onClickCb(operation.value, isAscend, isIntensity, layoutSt, shiftSt, forecastSt.predictions, decimalSt, integrationSt, multiplicitySt, waveLengthSt, cyclicvoltaPayload, curveSt, axesUnitsSt, detectorSt, dscMetaData, curveList, editPeakSt, thresList, scanSt, feature, hplcMsSt, sweepExtentSt),
+ children: children || /*#__PURE__*/(0, _jsxRuntime.jsx)(_PlayCircleOutline.default, {
className: classes.icon
})
})
@@ -321,7 +347,8 @@ const mapStateToProps = (state, props) => (
axesUnitsSt: state.axesUnits,
detectorSt: state.detector,
metaSt: state.meta,
- hplcMsSt: state.hplcMs
+ hplcMsSt: state.hplcMs,
+ sweepExtentSt: state.ui.sweepExtent
});
BtnSubmit.propTypes = {
classes: _propTypes.default.object.isRequired,
@@ -345,7 +372,11 @@ BtnSubmit.propTypes = {
axesUnitsSt: _propTypes.default.object.isRequired,
detectorSt: _propTypes.default.object.isRequired,
metaSt: _propTypes.default.object.isRequired,
- hplcMsSt: _propTypes.default.object
+ hplcMsSt: _propTypes.default.object,
+ sweepExtentSt: _propTypes.default.object,
+ disabled: _propTypes.default.bool,
+ className: _propTypes.default.string,
+ children: _propTypes.default.node
};
BtnSubmit.defaultProps = {
hplcMsSt: {}
diff --git a/dist/components/cmd_bar/r07_wavelength_btn.js b/dist/components/cmd_bar/r07_wavelength_btn.js
index 9b517427..183029cd 100644
--- a/dist/components/cmd_bar/r07_wavelength_btn.js
+++ b/dist/components/cmd_bar/r07_wavelength_btn.js
@@ -30,7 +30,7 @@ const styles = () => Object.assign({
}, _common.commonStyle);
const wavelengthSelect = (classes, waveLengthSt, layoutSt, updateWavelengthAct) => {
if (!_format.default.isXRDLayout(layoutSt)) {
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("i", {});
+ return null;
}
const onChange = e => updateWavelengthAct(e.target.value);
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.FormControl, {
@@ -65,10 +65,13 @@ const Wavelength = ({
waveLengthSt,
layoutSt,
updateWavelengthAct
-}) => /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
- className: classes.groupRight,
- children: wavelengthSelect(classes, waveLengthSt, layoutSt, updateWavelengthAct)
-});
+}) => {
+ if (!_format.default.isXRDLayout(layoutSt)) return null;
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
+ className: classes.groupRight,
+ children: wavelengthSelect(classes, waveLengthSt, layoutSt, updateWavelengthAct)
+ });
+};
const mapStateToProps = (state, props) => (
// eslint-disable-line
{
diff --git a/dist/components/cmd_bar/r08_change_axes.js b/dist/components/cmd_bar/r08_change_axes.js
index b8d3ee75..4c8a1051 100644
--- a/dist/components/cmd_bar/r08_change_axes.js
+++ b/dist/components/cmd_bar/r08_change_axes.js
@@ -131,7 +131,7 @@ const axisY = (classes, layoutSt, axesUnitsSt, updateYAxisAct, curveSt) => {
};
const showSelect = (classes, layoutSt, curveSt, axesUnitsSt, updateXAxisAct, updateYAxisAct) => {
if (!listLayoutToShow.includes(layoutSt)) {
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("i", {});
+ return null;
}
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
children: [axisX(classes, layoutSt, axesUnitsSt, updateXAxisAct, curveSt), axisY(classes, layoutSt, axesUnitsSt, updateYAxisAct, curveSt)]
@@ -161,6 +161,7 @@ const ChangeAxes = ({
});
}
}, [layoutSt, axes, curveIdx, updateYAxisAct]);
+ if (!listLayoutToShow.includes(layoutSt)) return null;
return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: classes.groupRight,
"data-testid": "ChangeAxes",
diff --git a/dist/components/cmd_bar/r09_detector.js b/dist/components/cmd_bar/r09_detector.js
index 380e6240..1ad7948c 100644
--- a/dist/components/cmd_bar/r09_detector.js
+++ b/dist/components/cmd_bar/r09_detector.js
@@ -30,7 +30,7 @@ const styles = () => Object.assign({
}, _common.commonStyle);
const detectorSelect = (classes, detectorSt, curveSt, layoutSt, updateDetectorAct) => {
if (!_format.default.isSECLayout(layoutSt)) {
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("i", {});
+ return null;
}
const {
curveIdx
@@ -80,10 +80,13 @@ const Detector = ({
curveSt,
layoutSt,
updateDetectorAct
-}) => /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
- className: classes.groupRight,
- children: detectorSelect(classes, detectorSt, curveSt, layoutSt, updateDetectorAct)
-});
+}) => {
+ if (!_format.default.isSECLayout(layoutSt)) return null;
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
+ className: classes.groupRight,
+ children: detectorSelect(classes, detectorSt, curveSt, layoutSt, updateDetectorAct)
+ });
+};
const mapStateToProps = (state, _props) => (
// eslint-disable-line
{
diff --git a/dist/components/cmd_bar/r10_cv_density.js b/dist/components/cmd_bar/r10_cv_density.js
index 4f850b0b..c2cf51a3 100644
--- a/dist/components/cmd_bar/r10_cv_density.js
+++ b/dist/components/cmd_bar/r10_cv_density.js
@@ -51,7 +51,7 @@ const CvDensityControls = ({
setAreaUnitAct,
toggleDensityAct
}) => {
- if (layoutSt !== _list_layout.LIST_LAYOUT.CYCLIC_VOLTAMMETRY) return /*#__PURE__*/(0, _jsxRuntime.jsx)("i", {});
+ if (layoutSt !== _list_layout.LIST_LAYOUT.CYCLIC_VOLTAMMETRY) return null;
const handleAreaChange = e => {
const raw = e.target.value;
if (raw === '') {
diff --git a/dist/components/common/draw.js b/dist/components/common/draw.js
index ad86fad9..0ae7d0c3 100644
--- a/dist/components/common/draw.js
+++ b/dist/components/common/draw.js
@@ -26,7 +26,7 @@ const drawDisplay = (klass, isHidden) => {
}
};
exports.drawDisplay = drawDisplay;
-const drawDestroy = klass => d3.select(`${klass} > *`).remove();
+const drawDestroy = klass => d3.select(klass).selectAll('*').remove();
exports.drawDestroy = drawDestroy;
const drawArrowOnCurve = (klass, isHidden) => {
if (isHidden) {
diff --git a/dist/components/d3_line/line_focus.js b/dist/components/d3_line/line_focus.js
index 113c3abe..35aac661 100644
--- a/dist/components/d3_line/line_focus.js
+++ b/dist/components/d3_line/line_focus.js
@@ -314,6 +314,10 @@ class LineFocus {
const dPks = this.mergedPeaks(editPeakSt);
const mpp = this.tags.pPath.selectAll('path').data(dPks);
mpp.exit().attr('class', 'exit').remove();
+ const clearPeakLabels = () => {
+ const bpTxt = this.tags.bpTxt.selectAll('text').data([]);
+ bpTxt.exit().attr('class', 'exit').remove();
+ };
const linePath = [{
x: -0.5,
y: 10
@@ -351,6 +355,8 @@ class LineFocus {
const bpTxt = this.tags.bpTxt.selectAll('text').data(dPks);
bpTxt.exit().attr('class', 'exit').remove();
bpTxt.enter().append('text').attr('class', 'peak-text').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(bpTxt).attr('id', d => `mpp${Math.round(1000 * d.x)}`).text(d => d.x.toFixed(2)).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y) - 25})`).on('click', (event, d) => this.onClickTarget(event, d));
+ } else {
+ clearPeakLabels();
}
}
drawInteg(integrationState) {
@@ -361,11 +367,29 @@ class LineFocus {
sameData
} = this.shouldUpdate;
if (sameXY && sameLySt && sameItSt && sameData) return;
+ const clearIntegralPaths = () => {
+ const empty = [];
+ const igbp = this.tags.igbPath.selectAll('path').data(empty);
+ igbp.exit().attr('class', 'exit').remove();
+ const igcp = this.tags.igcPath.selectAll('path').data(empty);
+ igcp.exit().attr('class', 'exit').remove();
+ const igtp = this.tags.igtPath.selectAll('text').data(empty);
+ igtp.exit().attr('class', 'exit').remove();
+ };
+ const clearAUC = () => {
+ const auc = this.tags.aucPath.selectAll('path').data([]);
+ auc.exit().attr('class', 'exit').remove();
+ };
const {
selectedIdx,
integrations
} = integrationState;
const selectedIntegration = integrations[selectedIdx];
+ if (selectedIntegration === false || selectedIntegration === undefined) {
+ clearIntegralPaths();
+ clearAUC();
+ return;
+ }
const {
stack,
refArea,
@@ -393,16 +417,15 @@ class LineFocus {
const igtp = this.tags.igtPath.selectAll('text').data(itgs);
igtp.exit().attr('class', 'exit').remove();
if (itgs.length === 0 || isDisable) {
- // remove drawn area under curve
- const auc = this.tags.aucPath.selectAll('path').data(stack);
- auc.exit().attr('class', 'exit').remove();
- auc.merge(auc);
- this.drawVisualSplitLines(showIntegSplit ? itgs : [], shift, ignoreRef);
+ clearIntegralPaths();
+ clearAUC();
return;
}
if (ignoreRef) {
+ clearIntegralPaths();
this.drawAUC(stack, shift);
} else {
+ clearAUC();
// rescale for zoom
const {
xt
@@ -469,14 +492,12 @@ class LineFocus {
multiplicities = []
} = mtplySt || {};
const selectedMulti = multiplicities[selectedIdx] || {};
- const {
- stack = [],
- smExtext = false,
- shift = 0
- } = selectedMulti;
- const hasValidExtent = extent => extent && Number.isFinite(extent.xL) && Number.isFinite(extent.xU);
- const mpys = stack.filter(m => hasValidExtent(m?.xExtent));
const isDisable = _cfg.default.btnCmdMpy(this.layout);
+ const hasMpy = !isDisable && selectedMulti?.stack?.length > 0;
+ const mpys = hasMpy ? selectedMulti.stack : [];
+ const smExtext = hasMpy ? selectedMulti.smExtext : false;
+ const shift = hasMpy ? selectedMulti.shift : 0;
+ const hasValidExtent = extent => extent && Number.isFinite(extent.xL) && Number.isFinite(extent.xU);
if (mpys.length === 0 || isDisable) return;
const activeExtent = hasValidExtent(smExtext) ? smExtext : mpys[0].xExtent;
// rescale for zoom
diff --git a/dist/components/d3_multi/index.js b/dist/components/d3_multi/index.js
index 9096bb2c..98da6326 100644
--- a/dist/components/d3_multi/index.js
+++ b/dist/components/d3_multi/index.js
@@ -27,6 +27,16 @@ react/no-unused-prop-types */
const W = Math.round(window.innerWidth * 0.90 * 9 / 12); // ROI
const H = Math.round(window.innerHeight * 0.90 * 0.85); // ROI
+const buildResetPayload = (feature, curveSt) => ({
+ ...feature,
+ curveIdx: curveSt.curveIdx
+});
+const hasActiveZoom = sweepExtentSt => {
+ if (!sweepExtentSt) return false;
+ return !!(sweepExtentSt.xExtent || sweepExtentSt.yExtent);
+};
+const canSkipReset = (sweepExtentSt, layoutSt, feature) => hasActiveZoom(sweepExtentSt) && layoutSt === feature?.operation?.layout;
+const isSameMultiComparison = (oldEntities, newEntities) => Array.isArray(oldEntities) && Array.isArray(newEntities) && oldEntities.length > 0 && oldEntities.length === newEntities.length;
class ViewerMulti extends _react.default.Component {
constructor(props) {
super(props);
@@ -82,6 +92,7 @@ class ViewerMulti extends _react.default.Component {
isUiNoBrushSt,
isHidden,
cyclicvoltaSt,
+ shiftSt,
integrationSt,
mtplySt,
axesUnitsSt,
@@ -113,6 +124,7 @@ class ViewerMulti extends _react.default.Component {
isUiVisualSplitIntgSt,
isUiNoBrushSt,
cyclicvoltaSt,
+ shiftSt,
integrationSt,
mtplySt,
uiSt
@@ -232,11 +244,12 @@ class ViewerMulti extends _react.default.Component {
const {
feature,
resetAllAct,
- entities
+ entities,
+ curveSt
} = this.props;
const oldEntities = prevProps.entities;
- if (oldEntities !== entities) {
- resetAllAct(feature);
+ if (oldEntities !== entities && !isSameMultiComparison(oldEntities, entities)) {
+ resetAllAct(buildResetPayload(feature, curveSt));
}
}
createMultiFocus(size, props) {
@@ -280,6 +293,7 @@ class ViewerMulti extends _react.default.Component {
isHidden,
resetAllAct,
cyclicvoltaSt,
+ shiftSt,
integrationSt,
mtplySt,
uiSt
@@ -287,8 +301,8 @@ class ViewerMulti extends _react.default.Component {
const size = this.getTargetSize(layoutSt);
this.currentSize = size;
(0, _draw.drawDestroy)(this.rootKlass);
- if (shouldReset) {
- resetAllAct(feature);
+ if (shouldReset && !canSkipReset(sweepExtentSt, layoutSt, feature)) {
+ resetAllAct(buildResetPayload(feature, curveSt));
}
const {
xxLabel,
@@ -311,6 +325,7 @@ class ViewerMulti extends _react.default.Component {
isUiVisualSplitIntgSt,
isUiNoBrushSt,
cyclicvoltaSt,
+ shiftSt,
integrationSt,
mtplySt,
uiSt
@@ -348,6 +363,7 @@ const mapStateToProps = (state, props) => ({
isUiVisualSplitIntgSt: _cfg.default.showIntegSplitTools(state.layout) && state.ui.sweepType === _list_ui.LIST_UI_SWEEP_TYPE.INTEGRATION_VISUAL_SPLIT,
isUiNoBrushSt: _list_ui.LIST_NON_BRUSH_TYPES.indexOf(state.ui.sweepType) < 0,
cyclicvoltaSt: state.cyclicvolta,
+ shiftSt: state.shift,
maxminPeakSt: (0, _chem.Feature2MaxMinPeak)(state, props),
integrationSt: state.integration.present,
mtplySt: state.multiplicity.present,
@@ -394,6 +410,7 @@ ViewerMulti.propTypes = {
removeVisualSplitLineAct: _propTypes.default.func.isRequired,
isHidden: _propTypes.default.bool,
cyclicvoltaSt: _propTypes.default.object.isRequired,
+ shiftSt: _propTypes.default.object.isRequired,
maxminPeakSt: _propTypes.default.object,
addNewCylicVoltaPairPeakAct: _propTypes.default.func.isRequired,
addCylicVoltaMaxPeakAct: _propTypes.default.func.isRequired,
diff --git a/dist/components/d3_multi/multi_focus.js b/dist/components/d3_multi/multi_focus.js
index 05d11c69..1d4e1f43 100644
--- a/dist/components/d3_multi/multi_focus.js
+++ b/dist/components/d3_multi/multi_focus.js
@@ -15,6 +15,7 @@ var _integration_split = require("../../helpers/integration_split");
var _list_layout = require("../../constants/list_layout");
var _format = _interopRequireDefault(require("../../helpers/format"));
var _chem = require("../../helpers/chem");
+var _shift = require("../../helpers/shift");
var _cfg = _interopRequireDefault(require("../../helpers/cfg"));
var _focus = require("../../helpers/focus");
var _integration = require("../../helpers/integration");
@@ -127,7 +128,8 @@ class MultiFocus {
prevDtPk,
prevSfPk,
prevData,
- prevYFactor
+ prevYFactor,
+ prevJcampIdx
} = this.shouldUpdate;
const {
xt,
@@ -141,6 +143,7 @@ class MultiFocus {
const sameSfPk = prevSfPk === this.tSfPeaks || Array.isArray(prevSfPk) && Array.isArray(this.tSfPeaks) && prevSfPk.length === this.tSfPeaks.length && prevSfPk.every((peak, idx) => peak === this.tSfPeaks[idx]);
const sameData = prevData === this.data.length;
const sameYFactor = prevYFactor === this.yTransformFactor;
+ const sameJcampIdx = prevJcampIdx === this.jcampIdx;
this.shouldUpdate = Object.assign({}, this.shouldUpdate, {
sameXY,
sameEpSt,
@@ -150,7 +153,8 @@ class MultiFocus {
sameDtPk,
sameSfPk,
sameData,
- sameYFactor // eslint-disable-line
+ sameYFactor,
+ sameJcampIdx // eslint-disable-line
});
}
resetShouldUpdate(prevEpSt) {
@@ -166,6 +170,7 @@ class MultiFocus {
const prevData = this.data.length;
const prevLySt = this.layout;
const prevYFactor = this.yTransformFactor;
+ const prevJcampIdx = this.jcampIdx;
this.shouldUpdate = Object.assign({}, this.shouldUpdate, {
prevXt,
prevYt,
@@ -176,7 +181,8 @@ class MultiFocus {
prevDtPk,
prevSfPk,
prevData,
- prevYFactor // eslint-disable-line
+ prevYFactor,
+ prevJcampIdx // eslint-disable-line
});
}
setTip() {
@@ -202,7 +208,7 @@ class MultiFocus {
transformYValue(y) {
return y * this.yTransformFactor;
}
- setDataParams(filterSeed, peaks, tTrEndPts, tSfPeaks, layout, cyclicvoltaSt, jcampIdx = 0) {
+ setDataParams(filterSeed, peaks, tTrEndPts, tSfPeaks, layout, cyclicvoltaSt, shiftSt, jcampIdx = 0) {
this.data = [];
this.otherLineData = [];
let filterSubLayoutValue = null;
@@ -214,7 +220,7 @@ class MultiFocus {
feature,
color
} = entry;
- const offset = (0, _chem.GetCyclicVoltaPreviousShift)(cyclicvoltaSt, jcampIdx);
+ const offset = _format.default.isCyclicVoltaLayout(layout) ? (0, _chem.GetCyclicVoltaPreviousShift)(cyclicvoltaSt, idx) : (0, _shift.shiftOffsetAtIndex)(shiftSt, idx);
let currData = (0, _chem.convertTopic)(topic, layout, feature, offset);
if (idx === jcampIdx) {
if (!_format.default.isCyclicVoltaLayout(layout)) {
@@ -439,9 +445,10 @@ class MultiFocus {
sameXY,
sameEpSt,
sameDtPk,
- sameSfPk
+ sameSfPk,
+ sameJcampIdx
} = this.shouldUpdate;
- if (!_format.default.isCyclicVoltaLayout(this.layout) && sameXY && sameEpSt && sameDtPk && sameSfPk) return;
+ if (!_format.default.isCyclicVoltaLayout(this.layout) && sameXY && sameEpSt && sameDtPk && sameSfPk && sameJcampIdx) return;
// rescale for zoom
const {
@@ -474,6 +481,10 @@ class MultiFocus {
}
const mpp = this.tags.pPath.selectAll('path').data(dPks);
mpp.exit().attr('class', 'exit').remove();
+ const clearPeakLabels = () => {
+ const bpTxt = this.tags.bpTxt.selectAll('text').data([]);
+ bpTxt.exit().attr('class', 'exit').remove();
+ };
const linePath = [{
x: -0.5,
y: 10
@@ -530,6 +541,8 @@ class MultiFocus {
const bpTxt = this.tags.bpTxt.selectAll('text').data(dPks);
bpTxt.exit().attr('class', 'exit').remove();
bpTxt.enter().append('text').attr('class', 'peak-text').attr('font-family', 'Helvetica').style('font-size', '12px').attr('fill', '#228B22').style('text-anchor', 'middle').merge(bpTxt).attr('id', d => `mpp${Math.round(1000 * d.x)}`).text(d => d.x.toFixed(2)).attr('transform', d => `translate(${xt(d.x)}, ${yt(d.y) - 25})`).on('click', (event, d) => this.onClickTarget(event, d));
+ } else {
+ clearPeakLabels();
}
mpp.attr('fill', (_, index) => {
return indexOfCVRefPeaks[index] === -1 ? 'blue' : 'red';
@@ -543,9 +556,10 @@ class MultiFocus {
sameXY,
sameEpSt,
sameDtPk,
- sameSfPk
+ sameSfPk,
+ sameJcampIdx
} = this.shouldUpdate;
- if (!_format.default.isCyclicVoltaLayout(this.layout) && sameXY && sameEpSt && sameDtPk && sameSfPk) return;
+ if (!_format.default.isCyclicVoltaLayout(this.layout) && sameXY && sameEpSt && sameDtPk && sameSfPk && sameJcampIdx) return;
// rescale for zoom
const {
@@ -594,29 +608,30 @@ class MultiFocus {
sameXY,
sameLySt,
sameItSt,
- sameData
+ sameData,
+ sameJcampIdx
} = this.shouldUpdate;
- if (sameXY && sameLySt && sameItSt && sameData) return;
+ if (sameXY && sameLySt && sameItSt && sameData && sameJcampIdx) return;
+ const clearIntegralPaths = () => {
+ const empty = [];
+ const igbp = this.tags.igbPath.selectAll('path').data(empty);
+ igbp.exit().attr('class', 'exit').remove();
+ const igcp = this.tags.igcPath.selectAll('path').data(empty);
+ igcp.exit().attr('class', 'exit').remove();
+ const igtp = this.tags.igtPath.selectAll('text').data(empty);
+ igtp.exit().attr('class', 'exit').remove();
+ };
+ const clearAUC = () => {
+ const auc = this.tags.aucPath.selectAll('path').data([]);
+ auc.exit().attr('class', 'exit').remove();
+ };
const {
integrations
} = integrationState;
const selectedIntegration = integrations[this.jcampIdx];
if (selectedIntegration === false || selectedIntegration === undefined) {
- Object.assign(this, {
- integrationSplitTargets: {
- stack: [],
- shift: 0,
- ignoreRef: false
- }
- });
- const itgs = [];
- const igbp = this.tags.igbPath.selectAll('path').data(itgs);
- igbp.exit().attr('class', 'exit').remove();
- const igcp = this.tags.igcPath.selectAll('path').data(itgs);
- igcp.exit().attr('class', 'exit').remove();
- const igtp = this.tags.igtPath.selectAll('text').data(itgs);
- igtp.exit().attr('class', 'exit').remove();
- this.drawVisualSplitLines([], 0, false);
+ clearIntegralPaths();
+ clearAUC();
return;
}
const {
@@ -646,16 +661,15 @@ class MultiFocus {
const igtp = this.tags.igtPath.selectAll('text').data(itgs);
igtp.exit().attr('class', 'exit').remove();
if (itgs.length === 0 || isDisable) {
- // remove drawn area under curve
- const auc = this.tags.aucPath.selectAll('path').data(stack);
- auc.exit().attr('class', 'exit').remove();
- auc.merge(auc);
- this.drawVisualSplitLines(showIntegSplit ? itgs : [], shift, ignoreRef);
+ clearIntegralPaths();
+ clearAUC();
return;
}
if (ignoreRef) {
+ clearIntegralPaths();
this.drawAUC(stack, shift);
} else {
+ clearAUC();
// rescale for zoom
const {
xt
@@ -714,43 +728,20 @@ class MultiFocus {
const {
sameXY,
sameLySt,
- sameMySt
+ sameMySt,
+ sameJcampIdx
} = this.shouldUpdate;
- if (sameXY && sameLySt && sameMySt) return;
+ if (sameXY && sameLySt && sameMySt && sameJcampIdx) return;
const {
multiplicities
} = mtplySt;
const selectedMulti = multiplicities[this.jcampIdx];
- if (selectedMulti === false || selectedMulti === undefined) {
- const mpys = [];
- const mpyb = this.tags.mpybPath.selectAll('path').data(mpys);
- mpyb.exit().attr('class', 'exit').remove();
- const mpyt1 = this.tags.mpyt1Path.selectAll('text').data(mpys);
- mpyt1.exit().attr('class', 'exit').remove();
- const mpyt2 = this.tags.mpyt2Path.selectAll('text').data(mpys);
- mpyt2.exit().attr('class', 'exit').remove();
- let mPeaks = mpys.map(m => {
- const {
- peaks,
- xExtent
- } = m;
- return peaks.map(p => Object.assign({}, p, {
- xExtent
- }));
- });
- mPeaks = [].concat(...mPeaks);
- const mpyp = this.tags.mpypPath.selectAll('path').data(mPeaks);
- mpyp.exit().attr('class', 'exit').remove();
- return;
- }
- const {
- stack = [],
- smExtext = false,
- shift = 0
- } = selectedMulti || {};
- const hasValidExtent = extent => extent && Number.isFinite(extent.xL) && Number.isFinite(extent.xU);
- const mpys = stack.filter(m => hasValidExtent(m?.xExtent));
const isDisable = _cfg.default.btnCmdMpy(this.layout);
+ const hasMpy = !isDisable && selectedMulti?.stack?.length > 0;
+ const mpys = hasMpy ? selectedMulti.stack : [];
+ const smExtext = hasMpy ? selectedMulti.smExtext : false;
+ const shift = hasMpy ? selectedMulti.shift : 0;
+ const hasValidExtent = extent => extent && Number.isFinite(extent.xL) && Number.isFinite(extent.xU);
if (mpys.length === 0 || isDisable) return;
const activeExtent = hasValidExtent(smExtext) ? smExtext : mpys[0].xExtent;
// rescale for zoom
@@ -893,6 +884,7 @@ class MultiFocus {
isUiVisualSplitIntgSt,
isUiNoBrushSt,
cyclicvoltaSt,
+ shiftSt,
integrationSt,
mtplySt,
uiSt
@@ -911,7 +903,7 @@ class MultiFocus {
this.root = d3.select(this.rootKlass).selectAll('.focus-main');
this.scales = (0, _init.InitScale)(this, this.reverseXAxis(layoutSt));
this.setTip();
- this.setDataParams(filterSeed, filterPeak, tTrEndPts, tSfPeaks, layoutSt, cyclicvoltaSt, jcampIdx);
+ this.setDataParams(filterSeed, filterPeak, tTrEndPts, tSfPeaks, layoutSt, cyclicvoltaSt, shiftSt, jcampIdx);
Object.assign(this, {
isUiSplitIntgSt,
isUiVisualSplitIntgSt
@@ -956,6 +948,7 @@ class MultiFocus {
isUiVisualSplitIntgSt,
isUiNoBrushSt,
cyclicvoltaSt,
+ shiftSt,
integrationSt,
mtplySt,
uiSt
@@ -971,7 +964,7 @@ class MultiFocus {
const jcampIdx = curveIdx;
this.isShowAllCurves = isShowAllCurve;
this.entities = entities;
- this.setDataParams(filterSeed, filterPeak, tTrEndPts, tSfPeaks, layoutSt, cyclicvoltaSt, jcampIdx);
+ this.setDataParams(filterSeed, filterPeak, tTrEndPts, tSfPeaks, layoutSt, cyclicvoltaSt, shiftSt, jcampIdx);
Object.assign(this, {
isUiSplitIntgSt,
isUiVisualSplitIntgSt
diff --git a/dist/components/panel/graph_selection.js b/dist/components/panel/graph_selection.js
index ad38202d..7165b25e 100644
--- a/dist/components/panel/graph_selection.js
+++ b/dist/components/panel/graph_selection.js
@@ -25,31 +25,63 @@ const styles = () => ({
backgroundColor: '#eee',
height: 22
},
- curve: {
- width: '100%'
- },
- line: {
- height: '2px',
- borderWidth: '0',
- margin: '0'
+ curveItem: {
+ display: 'flex',
+ alignItems: 'center',
+ width: '100%',
+ fontSize: '0.8em',
+ padding: '6px 8px',
+ margin: 0,
+ cursor: 'pointer'
},
curveDefault: {
- backgroundColor: '#fff',
- fontSize: '0.8em',
- margin: '0',
- padding: '10px 2px 2px 10px',
- maxWidth: '95%',
- overflowWrap: 'anywhere'
+ backgroundColor: '#fff'
},
curveSelected: {
- backgroundColor: '#2196f3',
- fontSize: '0.8em',
- color: '#fff',
- padding: '10px 2px 2px 10px',
- maxWidth: '95%',
+ backgroundColor: '#e0e0e0'
+ },
+ curveIndex: {
+ flexShrink: 0,
+ marginRight: '4px',
+ fontStyle: 'italic'
+ },
+ curveLabel: {
+ flexShrink: 0,
+ marginRight: '8px',
overflowWrap: 'anywhere'
+ },
+ colorBar: {
+ flex: 1,
+ height: '6px',
+ borderRadius: '1px',
+ minWidth: '24px',
+ alignSelf: 'center'
}
});
+const fallbackName = (entityFileNames, idx) => {
+ if (entityFileNames && idx < entityFileNames.length) {
+ return entityFileNames[idx];
+ }
+ return '';
+};
+const displayName = (spectra, idx, entityFileNames) => spectra?.title || spectra?.feature?.title || spectra?.spectrum?.title || fallbackName(entityFileNames, idx) || `Spectrum ${idx + 1}`;
+const renderCurveItem = (classes, item, curveIdx, onChange) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.ListItem, {
+ disablePadding: true,
+ onClick: () => onChange(item.idx),
+ className: (0, _classnames.default)(classes.curveItem, item.idx === curveIdx ? classes.curveSelected : classes.curveDefault),
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
+ className: classes.curveIndex,
+ children: item.name
+ }), item.label !== '' ? /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
+ className: classes.curveLabel,
+ children: item.label
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
+ className: classes.colorBar,
+ style: {
+ backgroundColor: item.color
+ }
+ })]
+}, item.idx);
const GraphSelectionPanel = ({
classes,
curveSt,
@@ -57,7 +89,9 @@ const GraphSelectionPanel = ({
subLayoutsInfo,
layoutSt,
selectCurveAct,
- toggleShowAllCurveAct
+ toggleShowAllCurveAct,
+ expand,
+ onExapnd
}) => {
let subLayoutValues = [];
if (subLayoutsInfo) {
@@ -92,40 +126,38 @@ const GraphSelectionPanel = ({
let itemsSubLayout = [];
if (selectedSubLayout && subLayoutValues.length > 1) {
const subLayout = subLayoutsInfo?.[resolvedSelectedSubLayout];
- itemsSubLayout = Array.isArray(subLayout) ? subLayout.map((spectra, idx) => {
- const spectraIdx = spectra.curveIdx;
- const {
- color
- } = spectra;
- let filename = '';
- if (entityFileNames && spectraIdx < entityFileNames.length) {
- filename = entityFileNames[spectraIdx];
- }
- return {
- name: `${idx + 1}.`,
- idx: spectraIdx,
- color,
- filename
- };
- }) : [];
+ try {
+ itemsSubLayout = Array.isArray(subLayout) ? subLayout.map((spectra, idx) => {
+ const spectraIdx = spectra.curveIdx;
+ const {
+ color
+ } = spectra;
+ return {
+ name: `${idx + 1}.`,
+ idx: spectraIdx,
+ color,
+ label: displayName(spectra, spectraIdx, entityFileNames)
+ };
+ }) : [];
+ } catch (e) {
+ console.log(e); //eslint-disable-line
+ }
}
const items = listCurves.map((spectra, idx) => {
const {
color
} = spectra;
- let filename = '';
- if (entityFileNames && idx < entityFileNames.length) {
- filename = entityFileNames[idx];
- }
return {
name: `${idx + 1}.`,
idx,
color,
- filename
+ label: displayName(spectra, idx, entityFileNames)
};
});
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Accordion, {
"data-testid": "GraphSelectionPanel",
+ expanded: expand,
+ onChange: onExapnd,
disableGutters: true,
sx: {
'&.MuiAccordion-root.Mui-expanded': {
@@ -179,58 +211,10 @@ const GraphSelectionPanel = ({
}, subLayout);
})
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.List, {
- children: itemsSubLayout.map(item => /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.ListItem, {
- onClick: () => onChange(item.idx),
- className: (0, _classnames.default)(item.idx === curveIdx ? classes.curveSelected : classes.curveDefault) // eslint-disable-line
- ,
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
- className: (0, _classnames.default)(classes.curve),
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("i", {
- children: item.name
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
- style: {
- float: 'right',
- width: '95%'
- },
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("hr", {
- className: (0, _classnames.default)(classes.line),
- style: {
- backgroundColor: item.color
- }
- }), item.filename !== '' ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
- children: ["File: ", item.filename]
- }) : null // eslint-disable-line
- ]
- })]
- })
- }, item.idx))
+ children: itemsSubLayout.map(item => renderCurveItem(classes, item, curveIdx, onChange))
})]
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.List, {
- children: items.map(item => /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.ListItem, {
- onClick: () => onChange(item.idx),
- className: (0, _classnames.default)(item.idx === curveIdx ? classes.curveSelected : classes.curveDefault) // eslint-disable-line
- ,
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
- className: (0, _classnames.default)(classes.curve),
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("i", {
- children: item.name
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
- style: {
- float: 'right',
- width: '95%'
- },
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("hr", {
- className: (0, _classnames.default)(classes.line),
- style: {
- backgroundColor: item.color
- }
- }), item.filename !== '' ? /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
- children: ["File: ", item.filename]
- }) : null // eslint-disable-line
- ]
- })]
- })
- }, item.idx))
+ children: items.map(item => renderCurveItem(classes, item, curveIdx, onChange))
})]
});
};
diff --git a/dist/components/panel/index.js b/dist/components/panel/index.js
index 80bc732a..9904b37e 100644
--- a/dist/components/panel/index.js
+++ b/dist/components/panel/index.js
@@ -48,7 +48,7 @@ class PanelViewer extends _react.default.Component {
constructor(props) {
super(props);
this.state = {
- expand: 'info'
+ expand: ['info', 'graph']
};
this.onToggleExpand = this.onToggleExpand.bind(this);
this.handleDescriptionChanged = this.handleDescriptionChanged.bind(this);
@@ -63,7 +63,7 @@ class PanelViewer extends _react.default.Component {
const {
expand
} = this.state;
- const nextExpand = input === expand ? '' : input;
+ const nextExpand = expand.includes(input) ? expand.filter(item => item !== input) : [...expand, input];
this.setState({
expand: nextExpand
});
@@ -96,6 +96,7 @@ class PanelViewer extends _react.default.Component {
const onExpandCompare = () => this.onToggleExpand('compare');
const onExpandCyclicVolta = () => this.onToggleExpand('cyclicvolta');
const onExpandGraphSelection = () => this.onToggleExpand('graph');
+ const isExpanded = name => expand.includes(name);
const {
listCurves
} = curveSt;
@@ -110,15 +111,15 @@ class PanelViewer extends _react.default.Component {
children: [hideGraphSelection ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_graph_selection.default, {
jcampIdx: jcampIdx,
entityFileNames: entityFileNames,
- expand: expand === 'graph',
- onExpand: onExpandGraphSelection,
+ expand: isExpanded('graph'),
+ onExapnd: onExpandGraphSelection,
subLayoutsInfo: subLayoutsInfo
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_info.default, {
entities: entities,
feature: feature,
integration: integration,
editorOnly: editorOnly,
- expand: expand === 'info',
+ expand: isExpanded('info'),
molSvg: molSvg,
exactMass: exactMass,
onExpand: onExpandInfo,
@@ -126,18 +127,18 @@ class PanelViewer extends _react.default.Component {
canChangeDescription: canChangeDescription,
onDescriptionChanged: this.handleDescriptionChanged
}), _cfg.default.hidePanelPeak(layoutSt) ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_peaks.default, {
- expand: expand === 'peak',
+ expand: isExpanded('peak'),
onExapnd: onExpandPeak
}), _cfg.default.hidePanelMpy(layoutSt) ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_multiplicity.default, {
- expand: expand === 'mpy',
+ expand: isExpanded('mpy'),
onExapnd: onExpandMpy
- }), _cfg.default.hidePanelCompare(layoutSt) || curveCount > 1 ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_compare.default, {
- expand: expand === 'compare',
+ }), _cfg.default.hidePanelCompare(layoutSt) || !listCurves || listCurves.length > 1 ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_compare.default, {
+ expand: isExpanded('compare'),
onExapnd: onExpandCompare
}), _cfg.default.hidePanelCyclicVolta(layoutSt) || hideCyclicVolta ? null : /*#__PURE__*/(0, _jsxRuntime.jsx)(_cyclic_voltamery_data.default, {
jcampIdx: jcampIdx,
feature: feature,
- expand: expand === 'cyclicvolta',
+ expand: isExpanded('cyclicvolta'),
onExapnd: onExpandCyclicVolta,
userManualLink: userManualLink ? userManualLink.cv : undefined
})]
diff --git a/dist/components/panel/info.js b/dist/components/panel/info.js
index 7e3e96bf..72c13c62 100644
--- a/dist/components/panel/info.js
+++ b/dist/components/panel/info.js
@@ -165,44 +165,6 @@ const handleDescriptionChanged = (content, delta, source, editor, onDescriptionC
if (!onDescriptionChanged) return;
onDescriptionChanged(normalizeQuillValue(content), delta, source, editor);
};
-const aucValue = (integration, hplcMsSt) => {
- const values = [];
- const stackIntegration = integration?.stack;
- if (Array.isArray(stackIntegration)) {
- let sumVal = 0.0;
- stackIntegration.forEach(inte => {
- if (inte.absoluteArea) {
- sumVal += inte.absoluteArea;
- }
- });
- sumVal = sumVal.toFixed(2);
- stackIntegration.forEach(inte => {
- if (inte.absoluteArea) {
- const areaVal = inte.absoluteArea.toFixed(2);
- const percent = (areaVal * 100 / sumVal).toFixed(2);
- const valStr = areaVal + " (" + percent + "%)"; // eslint-disable-line
- values.push(valStr);
- }
- });
- }
- const spectraList = hplcMsSt?.uvvis?.spectraList || [];
- const listWaveLength = hplcMsSt?.uvvis?.listWaveLength || [];
- spectraList.forEach((spectrum, idx) => {
- const wavelength = listWaveLength[idx];
- const integrations = spectrum?.integrations || [];
- if (integrations.length > 0) {
- const sumArea = integrations.reduce((sum, integ) => sum + (integ.absoluteArea ?? integ.area ?? 0), 0);
- const integrationStrings = integrations.map(integ => {
- const rawArea = integ.absoluteArea ?? integ.area ?? 0;
- const areaVal = rawArea.toFixed(2);
- const percent = sumArea > 0 ? (rawArea * 100 / sumArea).toFixed(2) : '0.00';
- return `${areaVal} (${percent}%)`;
- });
- values.push(`[${wavelength} nm]: ${integrationStrings.join(', ')}`);
- }
- });
- return values.join('\n');
-};
const SECData = ({
classes,
layout,
@@ -482,7 +444,7 @@ const InfoPanel = ({
children: "Area under curve (AUC):"
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("br", {}), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
className: (0, _classnames.default)(classes.tTxt, classes.tTxtSim, 'txt-sv-panel-txt'),
- children: aucValue(integration)
+ children: _format.default.formatHplcAucPanel(integration, feature)
})]
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(DSCData, {
classes: classes,
diff --git a/dist/helpers/chem.js b/dist/helpers/chem.js
index c22b0c25..ee5399d0 100644
--- a/dist/helpers/chem.js
+++ b/dist/helpers/chem.js
@@ -15,6 +15,7 @@ exports.convertTopic = exports.convertThresEndPts = void 0;
var _jcampconverter = _interopRequireDefault(require("jcampconverter"));
var _reselect = require("reselect");
var _shift = require("./shift");
+var _cfg = _interopRequireDefault(require("./cfg"));
var _format = _interopRequireDefault(require("./format"));
var _list_layout = require("../constants/list_layout");
var _integration = require("./integration");
@@ -63,21 +64,7 @@ const getShiftOffset = (state, _) => {
if (layout === _list_layout.LIST_LAYOUT.CYCLIC_VOLTAMMETRY && cyclicvolta) {
return GetCyclicVoltaShiftOffset(cyclicvolta, curveIdx);
}
- const {
- shift
- } = state;
- const {
- shifts
- } = shift;
- const selectedShift = shifts[curveIdx];
- if (!selectedShift) {
- return 0.0;
- }
- const {
- ref,
- peak
- } = selectedShift;
- return (0, _shift.FromManualToOffset)(ref, peak);
+ return (0, _shift.shiftOffsetAtIndex)(state.shift, curveIdx);
};
const calcXYK = (xs, ys, maxY, offset) => {
const sp = [];
diff --git a/dist/helpers/compass.js b/dist/helpers/compass.js
index 00e85277..c82f6da0 100644
--- a/dist/helpers/compass.js
+++ b/dist/helpers/compass.js
@@ -300,7 +300,7 @@ const ClickCompass = (event, focus) => {
} else if (isLcmsTicGraph) {
focus.clickUiTargetAct(pt, false, false, jcampIdx, false, 'lcms_tic');
} else {
- focus.clickUiTargetAct(pt, false);
+ focus.clickUiTargetAct(pt, false, 0, focus.jcampIdx);
}
};
exports.ClickCompass = ClickCompass;
diff --git a/dist/helpers/extractPeaksEdit.js b/dist/helpers/extractPeaksEdit.js
index c0d0433b..5537003a 100644
--- a/dist/helpers/extractPeaksEdit.js
+++ b/dist/helpers/extractPeaksEdit.js
@@ -31,24 +31,8 @@ var _integration = require("./integration");
var _submit = require("../features/lc-ms/submit");
/* eslint-disable max-len */
-const niOffset = (shiftSt, atIndex = 0) => {
- const {
- shifts
- } = shiftSt;
- const selectedShift = shifts[atIndex];
- if (!selectedShift) {
- return 0;
- }
- const {
- ref,
- peak
- } = selectedShift;
- const offset = (0, _shift.FromManualToOffset)(ref, peak);
- return offset;
-};
-const msOffset = () => 0;
const extractAutoPeaks = (feature, thresSt, shiftSt, layoutSt, atIndex = 0) => {
- const offset = _format.default.isMsLayout(layoutSt) || _format.default.isLCMsLayout(layoutSt) ? msOffset() : niOffset(shiftSt, atIndex);
+ const offset = _format.default.isMsLayout(layoutSt) || _format.default.isLCMsLayout(layoutSt) ? 0 : (0, _shift.shiftOffsetAtIndex)(shiftSt, atIndex);
const peaks = (0, _chem.Convert2Peak)(feature, thresSt.value, offset);
return peaks;
};
diff --git a/dist/helpers/format.js b/dist/helpers/format.js
index 24e07a64..109c814b 100644
--- a/dist/helpers/format.js
+++ b/dist/helpers/format.js
@@ -40,7 +40,7 @@ const spectraDigit = layout => {
}
};
const fixDigit = (input, precision) => {
- const output = input || 0.0;
+ const output = Number(input) || 0.0;
return output.toFixed(precision);
};
@@ -184,13 +184,15 @@ const spectraOps = {
tail: ''
}
};
+const shiftAnchorX = selectedShift => {
+ if (!selectedShift) return null;
+ const x = selectedShift.ref?.value ?? selectedShift.peak?.x;
+ return x == null ? null : x;
+};
const rmRef = (peaks, shift, atIndex = 0) => {
- if (!shift) return peaks;
- const {
- shifts
- } = shift;
- const selectedShift = shifts[atIndex];
- const refValue = selectedShift.ref.value || selectedShift.peak.x;
+ if (!shift?.shifts) return peaks;
+ const refValue = shiftAnchorX(shift.shifts[atIndex]);
+ if (refValue == null) return peaks;
return peaks.map(p => (0, _converter.IsSame)(p.x, refValue) ? null : p).filter(r => r != null);
};
const isValidLcmsWavelengthLabel = wl => Number.isFinite(wl) && wl > 0;
@@ -452,35 +454,90 @@ const formatedDLSIntensity = (peaks, maxY, decimal = 2, isAscend = true, isInten
}));
return ordered.map(o => `${o.x} nm (${o.y} %)`).join(', ');
};
-const formatedHplcUvVis = (peaks, decimal = 2, integration) => {
+const HPLC_RT_DECIMAL = 2;
+const HPLC_VALUE_DECIMAL = 2;
+const HPLC_RT_UNIT = 'min';
+const formatHplcRetentionTime = rt => `${fixDigit(rt, HPLC_RT_DECIMAL)} ${HPLC_RT_UNIT}`;
+const formatHplcAuc = area => fixDigit(area, HPLC_VALUE_DECIMAL);
+const findHplcPeakRetentionTime = (feature, xL, xU) => {
+ if (!feature?.data?.[0]) {
+ return (xL + xU) / 2;
+ }
+ const {
+ x,
+ y
+ } = feature.data[0];
+ let maxY = -Infinity;
+ let rt = (xL + xU) / 2;
+ for (let i = 0; i < x.length; i += 1) {
+ if (x[i] >= xL && x[i] <= xU && y[i] > maxY) {
+ maxY = y[i];
+ rt = x[i];
+ }
+ }
+ return rt;
+};
+const isSameHplcRt = (a, b) => fixDigit(a, HPLC_RT_DECIMAL) === fixDigit(b, HPLC_RT_DECIMAL);
+const integrationApexRt = (inte, feature, peaks) => {
+ if (feature?.data?.[0]) {
+ return findHplcPeakRetentionTime(feature, inte.xL, inte.xU);
+ }
+ if (!Array.isArray(peaks)) return null;
+ const peaksInRange = peaks.filter(p => p.x >= inte.xL && p.x <= inte.xU);
+ if (peaksInRange.length === 0) return null;
+ return peaksInRange.reduce((best, p) => p.y > best.y ? p : best, peaksInRange[0]).x;
+};
+const findIntegrationForPeak = (peakX, stack, peaks, feature) => {
+ if (!Array.isArray(stack)) return null;
+ const x = parseFloat(peakX);
+ return stack.find(s => {
+ if (s.xL > x || x > s.xU) return false;
+ const apexRt = integrationApexRt(s, feature, peaks);
+ return apexRt != null && isSameHplcRt(x, apexRt);
+ }) || null;
+};
+const formatHplcAucPanel = (integration, feature) => {
+ if (!integration) return '';
+ const stackIntegration = integration.stack;
+ if (!Array.isArray(stackIntegration)) return '';
+ const entries = stackIntegration.filter(inte => inte.absoluteArea).map(inte => ({
+ rt: findHplcPeakRetentionTime(feature, inte.xL, inte.xU),
+ area: inte.absoluteArea
+ }));
+ if (entries.length === 0) return '';
+ const sumVal = entries.reduce((sum, e) => sum + e.area, 0);
+ return entries.map(e => {
+ const areaVal = formatHplcAuc(e.area);
+ const percent = fixDigit(e.area * 100 / sumVal, HPLC_VALUE_DECIMAL);
+ return `${formatHplcRetentionTime(e.rt)}, AUC=${areaVal} (${percent}%)`;
+ }).join(', ');
+};
+const formatedHplcUvVis = (peaks, decimal = 2, integration, feature, isAscend = false) => {
let stack = [];
if (integration) {
stack = integration.stack;
}
- let ordered = {};
+ let bestByX = {};
peaks.forEach(p => {
- const x = fixDigit(p.x, decimal);
- const better = !ordered[x] || p.y > ordered[x];
+ const x = Number(p.x);
+ const better = bestByX[x] === undefined || p.y > bestByX[x];
if (better) {
- ordered = Object.assign({}, ordered, {
+ bestByX = Object.assign({}, bestByX, {
[x]: p.y
});
}
});
- ordered = Object.keys(ordered).map(k => ({
- x: k,
- y: ordered[k]
- }));
+ const sortFunc = isAscend ? (a, b) => a.x - b.x : (a, b) => b.x - a.x;
+ const ordered = Object.keys(bestByX).map(k => ({
+ x: parseFloat(k),
+ y: bestByX[k]
+ })).sort(sortFunc);
const arrResult = [];
ordered.forEach(o => {
- let pStr = `${o.x} (${o.y.toFixed(2)})`;
- if (stack) {
- stack.forEach(s => {
- if (s.xL <= o.x && s.xU >= o.x) {
- pStr = `${o.x} (${o.y.toFixed(2)}, AUC=${s.absoluteArea})`;
- }
- });
- }
+ const rt = formatHplcRetentionTime(o.x);
+ const yVal = o.y.toFixed(HPLC_VALUE_DECIMAL);
+ const inte = findIntegrationForPeak(o.x, stack, peaks, feature);
+ const pStr = inte?.absoluteArea ? `${rt} (${yVal}, AUC=${formatHplcAuc(inte.absoluteArea)})` : `${rt} (${yVal})`;
arrResult.push(pStr);
});
return arrResult.join(', ');
@@ -509,15 +566,9 @@ const formatedXRD = (peaks, isAscend = true, waveLength, temperature) => {
};
const rmShiftFromPeaks = (peaks, shift, atIndex = 0) => {
const peaksXY = (0, _converter.ToXY)(peaks);
- const {
- shifts
- } = shift;
- const selectedShift = shifts[atIndex];
- if (!selectedShift) {
- return peaks;
- }
- // const digit = spectraDigit(layout);
- const rmShiftX = selectedShift.ref.value || selectedShift.peak.x;
+ if (!shift?.shifts) return peaks;
+ const rmShiftX = shiftAnchorX(shift.shifts[atIndex]);
+ if (rmShiftX == null) return peaks;
const result = peaksXY.map(p => {
const srcX = parseFloat(p[0]);
const x = (0, _converter.IsSame)(srcX, rmShiftX) ? null : srcX;
@@ -542,7 +593,8 @@ const peaksBody = ({
atIndex = 0,
waveLength,
temperature,
- hplcMsSt = null
+ hplcMsSt = null,
+ feature
}) => {
const result = rmShiftFromPeaks(peaks, shift, atIndex);
const ascendFunc = (a, b) => parseFloat(a.x) - parseFloat(b.x);
@@ -563,7 +615,7 @@ const peaksBody = ({
return formatedUvVis(ordered, maxY, decimal, isAscend, isIntensity, boundary, false);
}
if (layout === _list_layout.LIST_LAYOUT.HPLC_UVVIS) {
- return formatedHplcUvVis(ordered, decimal, integration);
+ return formatedHplcUvVis(ordered, decimal, integration, feature, isAscend);
}
if (layout === _list_layout.LIST_LAYOUT.EMISSIONS) {
return formatedEmissions(ordered, maxY, decimal, isAscend, isIntensity, boundary, false);
@@ -581,11 +633,8 @@ const peaksBody = ({
};
const peaksWrapper = (layout, shift, atIndex = 0) => {
let solvTxt = '';
- const {
- shifts
- } = shift;
- const selectedShift = shifts[atIndex];
- if (selectedShift.ref.label) {
+ const selectedShift = shift?.shifts ? shift.shifts[atIndex] : shift;
+ if (selectedShift?.ref?.label) {
solvTxt = ` (${selectedShift.ref.label})`;
}
if (layout === _list_layout.LIST_LAYOUT.PLAIN || layout === _list_layout.LIST_LAYOUT.DLS_ACF) {
@@ -836,6 +885,8 @@ const Format = {
formatedXRD,
strNumberFixedLength,
inlineNotation,
- formatedLCMS
+ formatedLCMS,
+ formatHplcAucPanel,
+ formatedHplcUvVis
};
var _default = exports.default = Format;
\ No newline at end of file
diff --git a/dist/helpers/shift.js b/dist/helpers/shift.js
index 917f161e..5051a840 100644
--- a/dist/helpers/shift.js
+++ b/dist/helpers/shift.js
@@ -3,11 +3,35 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
-exports.VirtalPts = exports.RealPts = exports.FromManualToOffset = exports.CalcResidualX = void 0;
+exports.shiftOffsetAtIndex = exports.shiftEntryAtIndex = exports.normalizeShiftForFormatting = exports.listEntryAtIndex = exports.defaultEmptyShift = exports.VirtalPts = exports.RealPts = exports.FromManualToOffset = exports.CalcResidualX = void 0;
var _list_shift = require("../constants/list_shift");
/* eslint-disable prefer-object-spread, default-param-last */
-const shiftNone = _list_shift.LIST_SHIFT_13C[0];
+const shiftNone = _list_shift.LIST_SHIFT_1H[0];
+const defaultEmptyShift = exports.defaultEmptyShift = {
+ ref: shiftNone,
+ peak: false,
+ enable: true
+};
+const listEntryAtIndex = (list, index, fallback) => Array.isArray(list) && list[index] !== undefined ? list[index] : fallback;
+exports.listEntryAtIndex = listEntryAtIndex;
+const shiftEntryAtIndex = (shiftSt, atIndex = 0) => listEntryAtIndex(shiftSt?.shifts, atIndex, defaultEmptyShift);
+exports.shiftEntryAtIndex = shiftEntryAtIndex;
+const normalizeShiftForFormatting = (shift, atIndex = 0) => {
+ if (shift?.shifts) {
+ return {
+ shift,
+ atIndex
+ };
+ }
+ return {
+ shift: {
+ shifts: [shift || defaultEmptyShift]
+ },
+ atIndex: 0
+ };
+};
+exports.normalizeShiftForFormatting = normalizeShiftForFormatting;
const FromManualToOffset = (ref, peak) => {
if (!peak || ref.name === shiftNone.name) return 0;
const offset = peak.x - ref.value;
@@ -32,4 +56,12 @@ const RealPts = (pts, resX) => pts.map(pt => Object.assign({
x: pt.x - resX,
y: pt.y
}));
-exports.RealPts = RealPts;
\ No newline at end of file
+exports.RealPts = RealPts;
+const shiftOffsetAtIndex = (shiftSt, atIndex = 0) => {
+ const {
+ ref,
+ peak
+ } = shiftEntryAtIndex(shiftSt, atIndex);
+ return FromManualToOffset(ref, peak);
+};
+exports.shiftOffsetAtIndex = shiftOffsetAtIndex;
\ No newline at end of file
diff --git a/dist/index.js b/dist/index.js
index ac438caa..97acc0d8 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -8,6 +8,7 @@ var _reactQuill = _interopRequireDefault(require("react-quill"));
var _app = require("./app");
var _extractEntityLCMS = require("./helpers/extractEntityLCMS");
var _utils = require("./reducers/reducer_hplc_ms/utils");
+var _shift = require("./helpers/shift");
var _nmr1h_jcamp = _interopRequireDefault(require("./__tests__/fixtures/nmr1h_jcamp"));
var _nmr1h_2_jcamp = _interopRequireDefault(require("./__tests__/fixtures/nmr1h_2_jcamp"));
var _nmr13c_dept_jcamp = _interopRequireDefault(require("./__tests__/fixtures/nmr13c_dept_jcamp"));
@@ -68,17 +69,6 @@ const pickSelectedSpectrumFromPayload = payload => {
const selectedIdx = Number.isFinite(payload?.curveSt?.curveIdx) ? payload.curveSt.curveIdx : 0;
return spectraList[selectedIdx] || spectraList[0] || {};
};
-const normalizeShiftForFormatting = shift => {
- if (shift && Array.isArray(shift.shifts)) return shift;
- return {
- selectedIdx: 0,
- shifts: [shift || {
- ref: {},
- peak: false,
- enable: true
- }]
- };
-};
const nmr1HEntity = _app.FN.ExtractJcamp(_nmr1h_jcamp.default);
const nmr1HEntity2 = _app.FN.ExtractJcamp(_nmr1h_2_jcamp.default);
const nmr13CEntity = _app.FN.ExtractJcamp(_nmr13c_jcamp.default);
@@ -549,7 +539,7 @@ class DemoWriteIr extends _react.default.Component {
maxY,
minY
};
- const shiftForFormatting = normalizeShiftForFormatting(shift);
+ const shiftForFormatting = (0, _shift.normalizeShiftForFormatting)(shift);
const body = _app.FN.peaksBody({
peaks,
layout: safeLayout,
@@ -748,7 +738,7 @@ class DemoWriteIr extends _react.default.Component {
maxY,
minY
};
- const shiftForFormatting = normalizeShiftForFormatting(shift);
+ const shiftForFormatting = (0, _shift.normalizeShiftForFormatting)(shift);
const body = _app.FN.peaksBody({
peaks,
layout: safeLayout,
diff --git a/dist/layer_init.js b/dist/layer_init.js
index 17fd8df5..6a1ee548 100644
--- a/dist/layer_init.js
+++ b/dist/layer_init.js
@@ -22,9 +22,14 @@ var _multi_jcamps_viewer = _interopRequireDefault(require("./components/multi_jc
var _hplc_viewer = _interopRequireDefault(require("./components/hplc_viewer"));
var _curve = require("./actions/curve");
var _hplc_ms = require("./actions/hplc_ms");
+var _ui = require("./actions/ui");
var _jsxRuntime = require("react/jsx-runtime");
/* eslint-disable prefer-object-spread, default-param-last */
+const hasActiveZoom = sweepExtent => {
+ if (!sweepExtent) return false;
+ return !!(sweepExtent.xExtent || sweepExtent.yExtent);
+};
const styles = () => ({});
class LayerInit extends _react.default.Component {
static entitySignature(e) {
@@ -41,6 +46,20 @@ class LayerInit extends _react.default.Component {
}
constructor(props) {
super(props);
+ const {
+ sweepExtent,
+ restoreSweepExtentAct
+ } = props;
+ if (hasActiveZoom(sweepExtent)) {
+ restoreSweepExtentAct(sweepExtent);
+ } else {
+ // Clear any zoom left in the shared store by a previously opened
+ // spectrum, so it cannot block the RESETALL/layout sync on mount.
+ restoreSweepExtentAct({
+ xExtent: false,
+ yExtent: false
+ });
+ }
this.normChange = this.normChange.bind(this);
this.execReset = this.execReset.bind(this);
this.initReducer = this.initReducer.bind(this);
@@ -51,7 +70,7 @@ class LayerInit extends _react.default.Component {
this.execReset();
this.initReducer();
this.updateOthers();
- this.updateMultiEntities();
+ this.updateMultiEntities(true);
}
componentDidUpdate(prevProps) {
const {
@@ -68,7 +87,7 @@ class LayerInit extends _react.default.Component {
this.updateOthers();
}
if (prevProps.multiEntities !== multiEntities || prevProps.entity !== entity) {
- this.updateMultiEntities();
+ this.updateMultiEntities(false);
}
}
normChange(prevProps) {
@@ -95,14 +114,14 @@ class LayerInit extends _react.default.Component {
const {
entity,
updateMetaPeaksAct,
+ updateLayoutAct,
resetInitCommonAct,
resetInitMsAct,
resetInitNmrAct,
resetInitCommonWithIntergationAct,
resetDetectorAct,
updateDSCMetaDataAct,
- resetMultiplicityAct,
- updateLayoutAct
+ resetMultiplicityAct
} = this.props;
if (!entity || !entity.layout) return;
resetInitCommonAct();
@@ -111,9 +130,12 @@ class LayerInit extends _react.default.Component {
layout,
features = {}
} = entity;
+ // Sync the layout deterministically on every spectrum open. Otherwise it
+ // only updates via the d3 RESETALL, which can be skipped (active zoom or
+ // same multi-comparison curve count), leaving a stale layout from the
+ // previously opened spectrum.
updateLayoutAct(layout);
if (_format.default.isMsLayout(layout)) {
- // const { autoPeak, editPeak } = features; // TBD
const autoPeak = features.autoPeak || features[0];
const editPeak = features.editPeak || features[0];
const baseFeat = editPeak || autoPeak;
@@ -143,7 +165,8 @@ class LayerInit extends _react.default.Component {
dscMetaData
} = features;
updateDSCMetaDataAct(dscMetaData);
- } else {
+ }
+ if (!_format.default.isNmrLayout(layout)) {
resetMultiplicityAct();
}
}
@@ -165,7 +188,19 @@ class LayerInit extends _react.default.Component {
addOthersAct(others);
}
}
- updateMultiEntities() {
+ buildSetAllCurvesPayload(entities, isInitial) {
+ const {
+ curveIdx
+ } = this.props;
+ if (isInitial && Number.isFinite(curveIdx)) {
+ return {
+ entities,
+ curveIdx
+ };
+ }
+ return entities;
+ }
+ updateMultiEntities(isInitial = false) {
const {
multiEntities,
setAllCurvesAct,
@@ -196,17 +231,17 @@ class LayerInit extends _react.default.Component {
const isMultiSpectra = Array.isArray(multiEntities) && multiEntities.length > 1;
if (isMultiSpectra) {
const meta = _format.default.isLCMsLayout(entity.layout) ? lcmsCurveMeta() : undefined;
- setAllCurvesAct(multiEntities, meta);
+ setAllCurvesAct(this.buildSetAllCurvesPayload(multiEntities, isInitial), meta);
return;
}
if (_format.default.isLCMsLayout(entity.layout)) {
- const payload = Array.isArray(multiEntities) && multiEntities.length > 0 ? multiEntities : [entity];
- setAllCurvesAct(payload, lcmsCurveMeta());
+ const entities = Array.isArray(multiEntities) && multiEntities.length > 0 ? multiEntities : [entity];
+ setAllCurvesAct(this.buildSetAllCurvesPayload(entities, isInitial), lcmsCurveMeta());
return;
}
if (_format.default.isCyclicVoltaLayout(entity.layout)) {
- const payload = Array.isArray(multiEntities) && multiEntities.length > 0 ? multiEntities : [entity];
- setAllCurvesAct(payload);
+ const entities = Array.isArray(multiEntities) && multiEntities.length > 0 ? multiEntities : [entity];
+ setAllCurvesAct(this.buildSetAllCurvesPayload(entities, isInitial));
return;
}
setAllCurvesAct(false);
@@ -320,14 +355,23 @@ const mapDispatchToProps = dispatch => (0, _redux.bindActionCreators)({
addOthersAct: _jcamp.addOthers,
setAllCurvesAct: _curve.setAllCurves,
updateDSCMetaDataAct: _meta.updateDSCMetaData,
- clearHplcMsStateAct: _hplc_ms.clearHplcMsState
+ clearHplcMsStateAct: _hplc_ms.clearHplcMsState,
+ restoreSweepExtentAct: _ui.restoreSweepExtent
}, dispatch);
+LayerInit.defaultProps = {
+ multiEntities: undefined,
+ curveIdx: undefined,
+ sweepExtent: undefined
+};
LayerInit.propTypes = {
entity: _propTypes.default.object.isRequired,
multiEntities: _propTypes.default.array,
// eslint-disable-line
+ curveIdx: _propTypes.default.number,
+ sweepExtent: _propTypes.default.object,
entityFileNames: _propTypes.default.array,
// eslint-disable-line
+ restoreSweepExtentAct: _propTypes.default.func.isRequired,
others: _propTypes.default.object.isRequired,
cLabel: _propTypes.default.string.isRequired,
xLabel: _propTypes.default.string.isRequired,
diff --git a/dist/reducers/reducer_curve.js b/dist/reducers/reducer_curve.js
index 50cf529c..8137fe4d 100644
--- a/dist/reducers/reducer_curve.js
+++ b/dist/reducers/reducer_curve.js
@@ -18,10 +18,40 @@ const initialState = {
curveIdx: 0,
isShowAllCurve: false
};
+const normalizeSetAllCurvesPayload = payload => {
+ if (Array.isArray(payload)) {
+ return {
+ entities: payload,
+ curveIdx: undefined
+ };
+ }
+ if (payload && Array.isArray(payload.entities)) {
+ return {
+ entities: payload.entities,
+ curveIdx: payload.curveIdx
+ };
+ }
+ return {
+ entities: null,
+ curveIdx: undefined
+ };
+};
+const resolveCurveIdx = (entitiesLength, state, explicitIdx) => {
+ if (Number.isFinite(explicitIdx)) {
+ const maxIdx = Math.max(0, entitiesLength - 1);
+ return Math.min(Math.max(0, explicitIdx), maxIdx);
+ }
+ if (state.curveIdx >= 0 && state.curveIdx < entitiesLength) {
+ return state.curveIdx;
+ }
+ return 0;
+};
const setAllCurves = (state, action) => {
const {
- payload
- } = action;
+ entities: payloadEntities,
+ curveIdx: explicitIdx
+ } = normalizeSetAllCurvesPayload(action.payload);
+ const payload = payloadEntities ?? action.payload;
if (!payload) return {
...state,
curveIdx: 0,
@@ -69,11 +99,10 @@ const setAllCurves = (state, action) => {
spectra: spectra || entity.spectra
};
});
- const maxIdx = entities.length - 1;
- const safeCurveIdx = Math.min(state.curveIdx || 0, maxIdx);
+ const curveIdx = resolveCurveIdx(entities.length, state, explicitIdx);
return {
...state,
- curveIdx: safeCurveIdx,
+ curveIdx,
listCurves: entities
};
};
diff --git a/dist/reducers/reducer_edit_peak.js b/dist/reducers/reducer_edit_peak.js
index 35d38bff..b563f3fe 100644
--- a/dist/reducers/reducer_edit_peak.js
+++ b/dist/reducers/reducer_edit_peak.js
@@ -216,6 +216,10 @@ const editPeakReducer = (state = initialState, action) => {
return processShift(state, action);
case _action_type.EDITPEAK.CLEAR_ALL:
return clearAllPeaks(state, action);
+ case _action_type.CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, {
+ selectedIdx: action.payload
+ });
case _action_type.MANAGER.RESETALL:
return {
selectedIdx: 0,
diff --git a/dist/reducers/reducer_integration.js b/dist/reducers/reducer_integration.js
index 1b606355..43c657ce 100644
--- a/dist/reducers/reducer_integration.js
+++ b/dist/reducers/reducer_integration.js
@@ -421,18 +421,25 @@ const setFkr = (state, action) => {
};
const setShift = (state, action) => {
const {
- selectedIdx,
integrations
} = state;
- const selectedIntegration = integrations[selectedIdx];
- const shift = action.payload.prevOffset;
+ const {
+ prevOffset,
+ curveIdx
+ } = action.payload;
+ const targetIdx = Number.isFinite(curveIdx) ? curveIdx : state.selectedIdx;
+ let selectedIntegration = integrations[targetIdx];
+ if (selectedIntegration === false || selectedIntegration === undefined) {
+ selectedIntegration = defaultEmptyIntegration;
+ }
const newIntegration = Object.assign({}, selectedIntegration, {
- shift
+ shift: prevOffset
});
const newArrIntegration = [...integrations];
- newArrIntegration[selectedIdx] = newIntegration;
+ newArrIntegration[targetIdx] = newIntegration;
return Object.assign({}, state, {
- integrations: newArrIntegration
+ integrations: newArrIntegration,
+ selectedIdx: targetIdx
});
};
const resetAll = (state, action) => {
@@ -481,6 +488,10 @@ const integrationReducer = (state = initialState, action) => {
return clearAll(state, action);
case _action_type.EDITPEAK.SHIFT:
return setShift(state, action);
+ case _action_type.CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, {
+ selectedIdx: action.payload
+ });
case _action_type.MANAGER.RESETALL:
return state;
default:
diff --git a/dist/reducers/reducer_multiplicity.js b/dist/reducers/reducer_multiplicity.js
index 651182e1..a203f2fa 100644
--- a/dist/reducers/reducer_multiplicity.js
+++ b/dist/reducers/reducer_multiplicity.js
@@ -26,19 +26,26 @@ const defaultEmptyMultiplicity = {
edited: false
};
const setShift = (state, action) => {
- const shift = action.payload.prevOffset;
const {
- selectedIdx,
+ prevOffset,
+ curveIdx
+ } = action.payload;
+ const targetIdx = Number.isFinite(curveIdx) ? curveIdx : state.selectedIdx;
+ const {
multiplicities
} = state;
- const selectedMulti = multiplicities[selectedIdx];
+ let selectedMulti = multiplicities[targetIdx];
+ if (selectedMulti === false || selectedMulti === undefined) {
+ selectedMulti = defaultEmptyMultiplicity;
+ }
const newSelectedMulti = Object.assign({}, selectedMulti, {
- shift
+ shift: prevOffset
});
const newMultiplicities = [...multiplicities];
- newMultiplicities[selectedIdx] = newSelectedMulti;
+ newMultiplicities[targetIdx] = newSelectedMulti;
return Object.assign({}, state, {
- multiplicities: newMultiplicities
+ multiplicities: newMultiplicities,
+ selectedIdx: targetIdx
});
};
const rmFromStack = (state, action) => {
@@ -168,6 +175,10 @@ const multiplicityReducer = (state = initialState, action) => {
switch (action.type) {
case _action_type.EDITPEAK.SHIFT:
return setShift(state, action);
+ case _action_type.CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, {
+ selectedIdx: action.payload
+ });
case _action_type.INTEGRATION.RM_ONE:
return rmFromStack(state, action);
case _action_type.UI.SWEEP.SELECT_MULTIPLICITY_RDC:
diff --git a/dist/reducers/reducer_shift.js b/dist/reducers/reducer_shift.js
index 310ac7d8..81dd2645 100644
--- a/dist/reducers/reducer_shift.js
+++ b/dist/reducers/reducer_shift.js
@@ -26,11 +26,6 @@ const initialState = {
enable: true
}]
};
-const defaultEmptyShift = {
- ref: shiftNone,
- peak: false,
- enable: true
-};
const resetRef = payload => {
const {
shift,
@@ -71,22 +66,20 @@ const resetShift = (state, action) => {
curveIdx,
numberOfCurve
} = curvesInfo;
- const {
- shifts
- } = state;
+ const shifts = [...state.shifts];
let selectedShift = shifts[curveIdx];
if (selectedShift === false || selectedShift === undefined) {
- selectedShift = defaultEmptyShift;
+ selectedShift = _shift.defaultEmptyShift;
}
if (isMultiCurve) {
for (let idx = 0; idx < numberOfCurve; idx += 1) {
const checkShift = shifts[idx];
if (!checkShift) {
- shifts[idx] = defaultEmptyShift;
+ shifts[idx] = _shift.defaultEmptyShift;
}
}
}
- const newShift = Object.assign({}, defaultEmptyShift, {
+ const newShift = Object.assign({}, _shift.defaultEmptyShift, {
ref: resetRef(payload),
enable: resetEnable(payload)
});
@@ -104,7 +97,7 @@ const updateShift = (state, action) => {
} = state;
let selectedShift = shifts[selectedIdx];
if (selectedShift === false || selectedShift === undefined) {
- selectedShift = defaultEmptyShift;
+ selectedShift = _shift.defaultEmptyShift;
}
const newShift = Object.assign({}, selectedShift, {
ref: false,
@@ -129,7 +122,7 @@ const setRef = (state, action) => {
} = state;
let selectedShift = shifts[curveIdx];
if (selectedShift === false || selectedShift === undefined) {
- selectedShift = defaultEmptyShift;
+ selectedShift = _shift.defaultEmptyShift;
}
const newShift = Object.assign({}, selectedShift, {
ref: dataToSet,
@@ -154,7 +147,7 @@ const setPeak = (state, action) => {
} = state;
let selectedShift = shifts[curveIdx];
if (selectedShift === false || selectedShift === undefined) {
- selectedShift = defaultEmptyShift;
+ selectedShift = _shift.defaultEmptyShift;
}
const resX = (0, _shift.CalcResidualX)(selectedShift.ref, selectedShift.peak, dataToSet);
const trueApex = (0, _shift.RealPts)([dataToSet], resX)[0];
@@ -178,7 +171,7 @@ const removePeak = (state, action) => {
} = state;
let selectedShift = shifts[selectedIdx];
if (selectedShift === false || selectedShift === undefined) {
- selectedShift = defaultEmptyShift;
+ selectedShift = _shift.defaultEmptyShift;
}
const newShift = Object.assign({}, selectedShift, {
peak: false,
@@ -203,7 +196,7 @@ const addNegative = (state, action) => {
} = state;
let selectedShift = shifts[curveIdx];
if (selectedShift === false || selectedShift === undefined) {
- selectedShift = defaultEmptyShift;
+ selectedShift = _shift.defaultEmptyShift;
}
const rmApex = selectedShift.peak.x === dataToAdd.x;
if (!rmApex) {
@@ -237,7 +230,11 @@ const shiftReducer = (state = initialState, action) => {
return updateShift(initialState, action);
case _action_type.MANAGER.RESETSHIFT:
// case MANAGER.RESETALL:
- return resetShift(initialState, action);
+ return resetShift(state, action);
+ case _action_type.CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, {
+ selectedIdx: action.payload
+ });
default:
return state;
}
diff --git a/dist/reducers/reducer_threshold.js b/dist/reducers/reducer_threshold.js
index 7fc7f727..e60f7066 100644
--- a/dist/reducers/reducer_threshold.js
+++ b/dist/reducers/reducer_threshold.js
@@ -16,14 +16,12 @@ const initialState = {
lower: false
}]
};
-
-// const defaultThresHold = {
-// isEdit: true,
-// value: false,
-// upper: false,
-// lower: false,
-// };
-
+const defaultThresHold = {
+ isEdit: true,
+ value: false,
+ upper: false,
+ lower: false
+};
const setThresHoldValue = (state, action) => {
const {
payload
@@ -126,12 +124,16 @@ const setThresHoldLower = (state, action) => {
list: newListThres
});
};
-const setThresHoldIsEdit = state => {
+const setThresHoldIsEdit = (state, action) => {
+ const {
+ payload
+ } = action;
const {
list,
selectedIdx
} = state;
- const selectedThres = list[selectedIdx];
+ const curveIdx = payload && payload.curveIdx !== undefined ? payload.curveIdx : selectedIdx;
+ const selectedThres = list[curveIdx] || defaultThresHold;
const {
isEdit
} = selectedThres;
@@ -139,9 +141,10 @@ const setThresHoldIsEdit = state => {
isEdit: !isEdit
});
const newListThres = [...list];
- newListThres[selectedIdx] = newSelectedThres;
+ newListThres[curveIdx] = newSelectedThres;
return Object.assign({}, state, {
- list: newListThres
+ list: newListThres,
+ selectedIdx: curveIdx
});
};
const resetAll = (state, action) => {
@@ -151,6 +154,21 @@ const resetAll = (state, action) => {
const {
list
} = state;
+ if (payload && payload.curveIdx !== undefined) {
+ const {
+ curveIdx
+ } = payload;
+ const selectedThres = list[curveIdx] || defaultThresHold;
+ const newSelectedThres = Object.assign({}, selectedThres, {
+ value: payload.thresRef
+ });
+ const newListThres = [...list];
+ newListThres[curveIdx] = newSelectedThres;
+ return Object.assign({}, state, {
+ selectedIdx: curveIdx,
+ list: newListThres
+ });
+ }
const newList = list.map(item => ({
isEdit: item.isEdit,
value: payload && payload.thresRef,
@@ -201,6 +219,10 @@ const thresholdReducer = (state = initialState, action) => {
switch (action.type) {
case _action_type.CURVE.SET_ALL_CURVES:
return setListThreshold(state, action);
+ case _action_type.CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, {
+ selectedIdx: action.payload
+ });
case _action_type.THRESHOLD.UPDATE_VALUE:
return setThresHoldValue(state, action);
case _action_type.THRESHOLD.UPDATE_UPPER_VALUE:
@@ -210,7 +232,7 @@ const thresholdReducer = (state = initialState, action) => {
case _action_type.THRESHOLD.RESET_VALUE:
return setThresHoldValue(state, action);
case _action_type.THRESHOLD.TOGGLE_ISEDIT:
- return setThresHoldIsEdit(state);
+ return setThresHoldIsEdit(state, action);
case _action_type.MANAGER.RESET_INIT_COMMON:
return resetInitCommon(state);
case _action_type.MANAGER.RESETALL:
diff --git a/dist/sagas/saga_manager.js b/dist/sagas/saga_manager.js
index e87aec57..b4e04eaf 100644
--- a/dist/sagas/saga_manager.js
+++ b/dist/sagas/saga_manager.js
@@ -9,6 +9,13 @@ var _action_type = require("../constants/action_type");
const getLayout = state => state.layout;
const getCurveSt = state => state.curve;
const getIntegrationSt = state => state.integration.present;
+const defaultEmptyIntegration = {
+ stack: [],
+ refArea: 1,
+ refFactor: 1,
+ shift: 0,
+ edited: false
+};
function* resetShift(action) {
const curveSt = yield (0, _effects.select)(getCurveSt);
const layout = yield (0, _effects.select)(getLayout);
@@ -19,7 +26,7 @@ function* resetShift(action) {
curveIdx,
listCurves
} = curveSt;
- const numberOfCurve = listCurves.length;
+ const numberOfCurve = Array.isArray(listCurves) ? listCurves.length : 0;
yield (0, _effects.put)({
type: _action_type.MANAGER.RESETSHIFT,
payload: Object.assign(
@@ -44,22 +51,19 @@ function* resetInitNmr(action) {
integration,
simulation
} = action.payload;
- const {
- integrations
- } = integationSt;
- const newArrIntegration = [...integrations];
- newArrIntegration[curveIdx] = integration;
+ // Always reset: keeping the previous spectrum's integrations would
+ // display stale data when the new entity has none saved.
+ const newArrIntegration = new Array(curveIdx + 1).fill(defaultEmptyIntegration);
+ newArrIntegration[curveIdx] = integration || defaultEmptyIntegration;
const payload = Object.assign({}, integationSt, {
integrations: newArrIntegration,
selectedIdx: curveIdx
}); // eslint-disable-line
- if (integration) {
- yield (0, _effects.put)({
- type: _action_type.INTEGRATION.RESET_ALL_RDC,
- payload
- });
- }
+ yield (0, _effects.put)({
+ type: _action_type.INTEGRATION.RESET_ALL_RDC,
+ payload
+ });
if (simulation) {
yield (0, _effects.put)({
type: _action_type.SIMULATION.RESET_ALL_RDC,
@@ -76,22 +80,17 @@ function* resetInitCommonWithIntergation(action) {
const {
integration
} = action.payload;
- const {
- integrations
- } = integationSt;
- const newArrIntegration = [...integrations];
- newArrIntegration[curveIdx] = integration;
+ const newArrIntegration = new Array(curveIdx + 1).fill(defaultEmptyIntegration);
+ newArrIntegration[curveIdx] = integration || defaultEmptyIntegration;
const payload = Object.assign({}, integationSt, {
integrations: newArrIntegration,
selectedIdx: curveIdx
}); // eslint-disable-line
- if (integration) {
- yield (0, _effects.put)({
- type: _action_type.INTEGRATION.RESET_ALL_RDC,
- payload
- });
- }
+ yield (0, _effects.put)({
+ type: _action_type.INTEGRATION.RESET_ALL_RDC,
+ payload
+ });
}
const managerSagas = [(0, _effects.takeEvery)(_action_type.MANAGER.RESETALL, resetShift), (0, _effects.takeEvery)(_action_type.MANAGER.RESET_INIT_NMR, resetInitNmr), (0, _effects.takeEvery)(_action_type.MANAGER.RESET_INIT_COMMON_WITH_INTERGATION, resetInitCommonWithIntergation)];
var _default = exports.default = managerSagas;
\ No newline at end of file
diff --git a/dist/sagas/saga_multi_entities.js b/dist/sagas/saga_multi_entities.js
index ee648abd..16c89a4c 100644
--- a/dist/sagas/saga_multi_entities.js
+++ b/dist/sagas/saga_multi_entities.js
@@ -167,6 +167,36 @@ function* setCyclicVoltametryRef(action) {
}
});
}
+function* setInitShifts() {
+ const curveSt = yield (0, _effects.select)(getCurveSt);
+ const {
+ listCurves
+ } = curveSt;
+ if (!listCurves || listCurves.length <= 1) {
+ return;
+ }
+ const layoutSt = yield (0, _effects.select)(getLayoutSt);
+ const numberOfCurve = listCurves.length;
+ for (let index = 0; index < listCurves.length; index += 1) {
+ const {
+ feature
+ } = listCurves[index];
+ if (feature) {
+ yield (0, _effects.put)({
+ type: _action_type.MANAGER.RESETSHIFT,
+ payload: {
+ ...feature,
+ layout: layoutSt,
+ curvesInfo: {
+ isMultiCurve: true,
+ curveIdx: index,
+ numberOfCurve
+ }
+ }
+ });
+ }
+ }
+}
function* setInitIntegrations(action) {
// eslint-disable-line
const curveSt = yield (0, _effects.select)(getCurveSt);
@@ -230,5 +260,5 @@ function* setInitIntegrations(action) {
}
}
}
-const multiEntitiesSagas = [(0, _effects.takeEvery)(_action_type.CURVE.SET_ALL_CURVES, setCyclicVoltametry), (0, _effects.takeEvery)(_action_type.CURVE.SET_ALL_CURVES, setInitIntegrations), (0, _effects.takeEvery)(_action_type.CYCLIC_VOLTA_METRY.SET_FACTOR, setCyclicVoltametryRef)];
+const multiEntitiesSagas = [(0, _effects.takeEvery)(_action_type.CURVE.SET_ALL_CURVES, setCyclicVoltametry), (0, _effects.takeEvery)(_action_type.CURVE.SET_ALL_CURVES, setInitShifts), (0, _effects.takeEvery)(_action_type.CURVE.SET_ALL_CURVES, setInitIntegrations), (0, _effects.takeEvery)(_action_type.CYCLIC_VOLTA_METRY.SET_FACTOR, setCyclicVoltametryRef)];
var _default = exports.default = multiEntitiesSagas;
\ No newline at end of file
diff --git a/dist/sagas/saga_multiplicity.js b/dist/sagas/saga_multiplicity.js
index 56645954..86919b5b 100644
--- a/dist/sagas/saga_multiplicity.js
+++ b/dist/sagas/saga_multiplicity.js
@@ -11,6 +11,12 @@ var _multiplicity_manual = require("../helpers/multiplicity_manual");
const getMetaSt = state => state.meta;
const getCurveSt = state => state.curve;
const getMultiplicitySt = state => state.multiplicity.present;
+const defaultEmptyMultiplicity = {
+ stack: [],
+ shift: 0,
+ smExtext: false,
+ edited: false
+};
function* selectMpy(action) {
const metaSt = yield (0, _effects.select)(getMetaSt);
const mpySt = yield (0, _effects.select)(getMultiplicitySt);
@@ -247,31 +253,19 @@ function* resetInitNmr(action) {
const {
curveIdx
} = curveSt;
- const {
- multiplicities
- } = mpySt;
- const newMultiplicities = [...multiplicities];
- newMultiplicities[curveIdx] = multiplicity;
+ // Always reset: keeping the previous spectrum's multiplicities would
+ // display stale data when the new entity has none saved.
+ const newMultiplicities = new Array(curveIdx + 1).fill(defaultEmptyMultiplicity);
+ newMultiplicities[curveIdx] = multiplicity || defaultEmptyMultiplicity;
const payload = Object.assign({}, mpySt, {
multiplicities: newMultiplicities,
selectedIdx: curveIdx
}); // eslint-disable-line
- if (multiplicity) {
- yield (0, _effects.put)({
- type: _action_type.MULTIPLICITY.RESET_ALL_RDC,
- payload
- });
- }
- // const metaSt = yield select(getMetaSt);
- // const mpySt = yield select(getMultiplicitySt);
-
- // if (!multiplicity) {
- // yield put({
- // type: MULTIPLICITY.RESET_ALL_RDC,
- // payload: mpySt,
- // });
- // }
+ yield (0, _effects.put)({
+ type: _action_type.MULTIPLICITY.RESET_ALL_RDC,
+ payload
+ });
// const { stack } = multiplicity;
// const newStack = stack.map((k) => {
diff --git a/dist/sagas/saga_ui.js b/dist/sagas/saga_ui.js
index b321663e..6836bf83 100644
--- a/dist/sagas/saga_ui.js
+++ b/dist/sagas/saga_ui.js
@@ -218,13 +218,15 @@ function* clickUiTarget(action) {
onPeak,
voltammetryPeakIdx,
onPecker,
- sourceHint
+ sourceHint,
+ jcampIdx
} = action;
const uiSweepType = yield (0, _effects.select)(getUiSweepType);
const curveState = yield (0, _effects.select)(getCurveState);
const {
curveIdx
} = curveState;
+ const targetCurveIdx = Number.isFinite(jcampIdx) ? jcampIdx : curveIdx;
const hplcMsState = yield (0, _effects.select)(getHplcMsState);
const {
uvvis
@@ -243,11 +245,11 @@ function* clickUiTarget(action) {
return;
}
if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.PEAK_ADD && !onPeak) {
- if (isLcmsLayout) {
- const spectrumId = hplcMsState?.uvvis?.selectedWaveLength;
- if (spectrumId == null) return;
- const currentPeaks = hplcMsState?.uvvis?.currentSpectrum?.peaks || [];
- const updatedPeaks = [...currentPeaks, payload];
+ const spectrumId = hplcMsState?.uvvis?.selectedWaveLength;
+ if (isLcmsLayout && spectrumId == null) return;
+ const currentPeaks = hplcMsState?.uvvis?.currentSpectrum?.peaks || [];
+ const updatedPeaks = [...currentPeaks, payload];
+ if (isLcmsLayout && spectrumId != null) {
yield (0, _effects.put)({
type: _action_type.HPLC_MS.UPDATE_HPLCMS_PEAKS,
payload: {
@@ -260,7 +262,7 @@ function* clickUiTarget(action) {
type: _action_type.EDITPEAK.ADD_POSITIVE,
payload: {
dataToAdd: payload,
- curveIdx
+ curveIdx: targetCurveIdx
}
});
}
@@ -275,7 +277,7 @@ function* clickUiTarget(action) {
type: _action_type.EDITPEAK.ADD_NEGATIVE,
payload: {
dataToAdd: payload,
- curveIdx
+ curveIdx: targetCurveIdx
}
});
}
@@ -284,7 +286,7 @@ function* clickUiTarget(action) {
type: _action_type.SHIFT.SET_PEAK,
payload: {
dataToSet: payload,
- curveIdx
+ curveIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.INTEGRATION_RM && onPeak) {
@@ -298,7 +300,7 @@ function* clickUiTarget(action) {
type: _action_type.INTEGRATION.RM_ONE,
payload: {
dataToRemove: payload,
- curveIdx
+ curveIdx: targetCurveIdx
}
});
}
@@ -307,7 +309,7 @@ function* clickUiTarget(action) {
type: _action_type.INTEGRATION.RM_ONE,
payload: {
dataToRemove: payload,
- curveIdx
+ curveIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.INTEGRATION_SET_REF && onPeak) {
@@ -315,7 +317,7 @@ function* clickUiTarget(action) {
type: _action_type.INTEGRATION.SET_REF,
payload: {
refData: payload,
- curveIdx
+ curveIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.MULTIPLICITY_ONE_CLICK && onPeak) {
@@ -329,7 +331,7 @@ function* clickUiTarget(action) {
type: _action_type.MULTIPLICITY.ONE_CLICK_BY_UI,
payload: {
payloadData: xExtent,
- curveIdx
+ curveIdx: targetCurveIdx
}
});
} else if (xL && xU) {
@@ -340,7 +342,7 @@ function* clickUiTarget(action) {
xL,
xU
},
- curveIdx
+ curveIdx: targetCurveIdx
}
});
}
@@ -360,7 +362,7 @@ function* clickUiTarget(action) {
payload: {
peak: payload,
index: voltammetryPeakIdx,
- jcampIdx: curveIdx
+ jcampIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_RM_MAX_PEAK && onPeak) {
@@ -368,7 +370,7 @@ function* clickUiTarget(action) {
type: _action_type.CYCLIC_VOLTA_METRY.REMOVE_MAX_PEAK,
payload: {
index: voltammetryPeakIdx,
- jcampIdx: curveIdx
+ jcampIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_ADD_MIN_PEAK && !onPeak) {
@@ -377,7 +379,7 @@ function* clickUiTarget(action) {
payload: {
peak: payload,
index: voltammetryPeakIdx,
- jcampIdx: curveIdx
+ jcampIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_RM_MIN_PEAK && onPeak) {
@@ -385,7 +387,7 @@ function* clickUiTarget(action) {
type: _action_type.CYCLIC_VOLTA_METRY.REMOVE_MIN_PEAK,
payload: {
index: voltammetryPeakIdx,
- jcampIdx: curveIdx
+ jcampIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_ADD_PECKER && !onPecker) {
@@ -394,7 +396,7 @@ function* clickUiTarget(action) {
payload: {
peak: payload,
index: voltammetryPeakIdx,
- jcampIdx: curveIdx
+ jcampIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_RM_PECKER && onPecker) {
@@ -402,7 +404,7 @@ function* clickUiTarget(action) {
type: _action_type.CYCLIC_VOLTA_METRY.REMOVE_PECKER,
payload: {
index: voltammetryPeakIdx,
- jcampIdx: curveIdx
+ jcampIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_SET_REF && onPeak) {
@@ -410,7 +412,7 @@ function* clickUiTarget(action) {
type: _action_type.CYCLIC_VOLTA_METRY.SET_REF,
payload: {
index: voltammetryPeakIdx,
- jcampIdx: curveIdx
+ jcampIdx: targetCurveIdx
}
});
} else if (uiSweepType === _list_ui.LIST_UI_SWEEP_TYPE.PEAK_GROUP_SELECT) {
diff --git a/src/__tests__/units/components/cmd_bar/03_peak.test.js b/src/__tests__/units/components/cmd_bar/03_peak.test.js
index 32463fa3..cc4bbdc1 100644
--- a/src/__tests__/units/components/cmd_bar/03_peak.test.js
+++ b/src/__tests__/units/components/cmd_bar/03_peak.test.js
@@ -9,7 +9,7 @@ import { LIST_LAYOUT } from '../../../../constants/list_layout';
const mockStore = configureStore([]);
const store = mockStore({
ui:{ sweepType: LIST_UI_SWEEP_TYPE.ZOOMIN },
- layout: LIST_LAYOUT.MS,
+ layout: LIST_LAYOUT.IR,
curve: { curveIdx: 0 },
editPeak: {
present: {
diff --git a/src/__tests__/units/components/cmd_bar/r05_submit_btn.test.js b/src/__tests__/units/components/cmd_bar/r05_submit_btn.test.js
index 07fc359c..f0f3c5c9 100644
--- a/src/__tests__/units/components/cmd_bar/r05_submit_btn.test.js
+++ b/src/__tests__/units/components/cmd_bar/r05_submit_btn.test.js
@@ -5,6 +5,7 @@ import '@testing-library/jest-dom';
import BtnSubmit, { computeCvYScaleFactor } from '../../../../components/cmd_bar/r05_submit_btn';
import Format from '../../../../helpers/format';
+import { defaultEmptyShift } from '../../../../helpers/shift';
jest.mock('../../../../helpers/extractPeaksEdit', () => ({
extractPeaksEdit: () => [{ x: 1, y: 2 }],
@@ -32,6 +33,7 @@ const buildBaseState = (overrides = {}) => ({
detector: {},
meta: { dscMetaData: {} },
hplcMs: {},
+ ui: { sweepExtent: { xExtent: false, yExtent: false } },
...overrides,
});
@@ -92,6 +94,29 @@ describe('', () => {
expect(payload.curveSt).toEqual({ curveIdx: 1 });
});
+ it('sends a default shift entry when the curve index is missing', () => {
+ const operationValue = jest.fn();
+ const state = buildBaseState({
+ layout: 'HPLC_UVVIS',
+ shift: { shifts: [defaultEmptyShift] },
+ curve: {
+ curveIdx: 1,
+ listCurves: [
+ { feature: { xUnit: 'min', yUnit: 'mAU', scanAutoTarget: 1, thresRef: 3 } },
+ { feature: { xUnit: 'min', yUnit: 'mAU', scanAutoTarget: 2, thresRef: 4 } },
+ ],
+ },
+ threshold: { list: [{ value: 10 }, { value: 20 }] },
+ axesUnits: { axes: [{ xUnit: '', yUnit: '' }, { xUnit: '', yUnit: '' }] },
+ });
+
+ renderBtnSubmit(state, operationValue);
+
+ const { shift } = operationValue.mock.calls[0][0].spectra_list[1];
+ expect(shift).toEqual(defaultEmptyShift);
+ expect(shift).not.toHaveProperty('shifts');
+ });
+
it('controls presence/absence of keepPred and simulatenmr', () => {
const withFlagsCb = jest.fn();
const noFlagsCb = jest.fn();
diff --git a/src/__tests__/units/helpers/format.test.tsx b/src/__tests__/units/helpers/format.test.tsx
index 7e3d0e1e..b5f618ce 100644
--- a/src/__tests__/units/helpers/format.test.tsx
+++ b/src/__tests__/units/helpers/format.test.tsx
@@ -139,7 +139,60 @@ describe('Test format helper', () => {
it('Get peaks for HPLC layout', () => {
params.layout = LIST_LAYOUT.HPLC_UVVIS
const body = Format.peaksBody(params)
- expect(body).toEqual('2.0 (2.00), 1.0 (1.00)')
+ expect(body).toEqual('2.00 min (2.00), 1.00 min (1.00)')
+ })
+
+ it('Get peaks for HPLC layout with integration', () => {
+ params.layout = LIST_LAYOUT.HPLC_UVVIS
+ params.integration = {
+ stack: [
+ { xL: 1.5, xU: 2.5, absoluteArea: 1234.5678 },
+ { xL: 0.5, xU: 1.5, absoluteArea: 987.6543 },
+ ],
+ }
+ const body = Format.peaksBody(params)
+ expect(body).toEqual(
+ '2.00 min (2.00, AUC=1234.57), 1.00 min (1.00, AUC=987.65)',
+ )
+ })
+
+ it('Does not assign AUC to peaks inside integration but not at apex', () => {
+ params.layout = LIST_LAYOUT.HPLC_UVVIS
+ params.isAscend = true
+ params.peaks = [
+ { x: 16.99, y: 319.83 },
+ { x: 14.05, y: 401.21 },
+ { x: 13.71, y: -0.77 },
+ ]
+ params.integration = {
+ stack: [
+ { xL: 13.5, xU: 14.5, absoluteArea: 31467.89 },
+ { xL: 16.5, xU: 17.5, absoluteArea: 31447.95 },
+ ],
+ }
+ const body = Format.peaksBody(params)
+ expect(body).toEqual(
+ '13.71 min (-0.77), 14.05 min (401.21, AUC=31467.89), 16.99 min (319.83, AUC=31447.95)',
+ )
+ })
+
+ it('Format HPLC AUC panel with retention time', () => {
+ const integration = {
+ stack: [
+ { xL: 12.5, xU: 13.5, absoluteArea: 1000 },
+ { xL: 15.5, xU: 16.5, absoluteArea: 2000 },
+ ],
+ }
+ const feature = {
+ data: [{
+ x: [12, 13, 14, 15, 16, 17],
+ y: [10, 50, 20, 15, 40, 10],
+ }],
+ }
+ const panel = Format.formatHplcAucPanel(integration, feature)
+ expect(panel).toEqual(
+ '13.00 min, AUC=1000.00 (33.33%), 16.00 min, AUC=2000.00 (66.67%)',
+ )
})
it('Get peaks for Emission layout', () => {
@@ -277,6 +330,12 @@ describe('Test format helper', () => {
const removedPeaks = Format.rmRef(peaks, shift)
expect(removedPeaks).toEqual([{x: 2.04, y: 2}])
})
+
+ it('Returns peaks unchanged when shift index is missing', () => {
+ const shift = { shifts: [{ ref: LIST_SHIFT_1H[1] }] }
+ const removedPeaks = Format.rmRef(peaks, shift, 1)
+ expect(removedPeaks).toEqual(peaks)
+ })
})
})
diff --git a/src/__tests__/units/helpers/shift.test.tsx b/src/__tests__/units/helpers/shift.test.tsx
index 47df37ad..38c2a304 100644
--- a/src/__tests__/units/helpers/shift.test.tsx
+++ b/src/__tests__/units/helpers/shift.test.tsx
@@ -1,4 +1,6 @@
-import { CalcResidualX, FromManualToOffset, RealPts, VirtalPts } from "../../../helpers/shift";
+import {
+ CalcResidualX, FromManualToOffset, RealPts, VirtalPts, shiftOffsetAtIndex,
+} from "../../../helpers/shift";
import { LIST_SHIFT_1H, LIST_SHIFT_13C } from "../../../constants/list_shift";
describe('Test helper for shift', () => {
@@ -65,6 +67,23 @@ describe('Test helper for shift', () => {
})
})
+ describe('Test shift offset at index', () => {
+ it('Returns zero when shift state is missing', () => {
+ expect(shiftOffsetAtIndex(null, 0)).toEqual(0)
+ })
+
+ it('Returns offset for the requested curve index', () => {
+ const shiftSt = {
+ shifts: [
+ { ref: LIST_SHIFT_1H[0], peak: false },
+ { ref: LIST_SHIFT_1H[1], peak: { x: 1.5, y: 2 } },
+ ],
+ }
+ expect(shiftOffsetAtIndex(shiftSt, 0)).toEqual(0)
+ expect(shiftOffsetAtIndex(shiftSt, 1)).toEqual(-0.54)
+ })
+ })
+
describe('Test get real points', () => {
it('No points', () => {
const virtualPoints = RealPts([], 18.0)
diff --git a/src/__tests__/units/reducers/reducer_curve.test.tsx b/src/__tests__/units/reducers/reducer_curve.test.tsx
index 531d50eb..8cfd1b97 100644
--- a/src/__tests__/units/reducers/reducer_curve.test.tsx
+++ b/src/__tests__/units/reducers/reducer_curve.test.tsx
@@ -58,6 +58,24 @@ describe('Test redux curve reducer', () => {
expect(maxminPeak).toBeNull()
})
+ it('Preserves the selected curve index when reloading all curves', () => {
+ action.type = CURVE.SET_ALL_CURVES
+ const entity = ExtractJcamp(nmr1HJcamp)
+ curveState = { listCurves: [], curveIdx: 2 }
+ action.payload = [ entity, entity, entity ]
+ const { curveIdx } = curveReducer(curveState, action)
+ expect(curveIdx).toEqual(2)
+ })
+
+ it('Uses an explicit curve index when provided', () => {
+ action.type = CURVE.SET_ALL_CURVES
+ const entity = ExtractJcamp(nmr1HJcamp)
+ curveState = { listCurves: [], curveIdx: 0 }
+ action.payload = { entities: [ entity, entity, entity ], curveIdx: 1 }
+ const { curveIdx } = curveReducer(curveState, action)
+ expect(curveIdx).toEqual(1)
+ })
+
it('Toggle show all curves', () => {
action.type = CURVE.SET_SHOULD_SHOW_ALL_CURVES
action.payload = true
diff --git a/src/__tests__/units/reducers/reducer_integration.test.tsx b/src/__tests__/units/reducers/reducer_integration.test.tsx
index 602d30e0..62ad9bcd 100644
--- a/src/__tests__/units/reducers/reducer_integration.test.tsx
+++ b/src/__tests__/units/reducers/reducer_integration.test.tsx
@@ -838,3 +838,42 @@ describe('Test redux reducer for integrations', () => {
expect(newState).toBe(state);
});
});
+
+import { EDITPEAK, CURVE } from '../../../constants/action_type';
+
+describe('Test redux integration reducer (per-curve)', () => {
+ const baseIntegration = {
+ stack: [{ xL: 1, xU: 2, area: 1, absoluteArea: 1 }],
+ refArea: 1,
+ refFactor: 1,
+ shift: 0,
+ edited: false,
+ };
+
+ it('updates shift on the curve index from the payload', () => {
+ const state = {
+ selectedIdx: 0,
+ integrations: [baseIntegration, { ...baseIntegration, shift: 0 }],
+ };
+ const action = {
+ type: EDITPEAK.SHIFT,
+ payload: { prevOffset: 0.42, curveIdx: 1 },
+ };
+ const nextState = integrationReducer(state, action);
+ expect(nextState.integrations[1].shift).toEqual(0.42);
+ expect(nextState.integrations[0].shift).toEqual(0);
+ expect(nextState.selectedIdx).toEqual(1);
+ });
+
+ it('syncs selectedIdx when the working curve changes', () => {
+ const state = {
+ selectedIdx: 0,
+ integrations: [baseIntegration],
+ };
+ const nextState = integrationReducer(state, {
+ type: CURVE.SELECT_WORKING_CURVE,
+ payload: 2,
+ });
+ expect(nextState.selectedIdx).toEqual(2);
+ });
+});
diff --git a/src/actions/threshold.js b/src/actions/threshold.js
index 001a4cdb..0b3fc4a8 100644
--- a/src/actions/threshold.js
+++ b/src/actions/threshold.js
@@ -7,10 +7,10 @@ const updateThresholdValue = (payload) => (
}
);
-const resetThresholdValue = () => (
+const resetThresholdValue = (payload = false) => (
{
type: THRESHOLD.RESET_VALUE,
- payload: false,
+ payload,
}
);
diff --git a/src/actions/ui.js b/src/actions/ui.js
index f1c43479..75c111f3 100644
--- a/src/actions/ui.js
+++ b/src/actions/ui.js
@@ -48,22 +48,27 @@ const scrollUiWheel = (payload) => (
}
);
-const clickUiTarget = (
- payload,
- onPeak,
- voltammetryPeakIdx = 0,
- jcampIdx = 0,
- onPecker = false,
- sourceHint = null,
-) => ({
- type: UI.CLICK_TARGET,
- payload,
- onPeak,
- voltammetryPeakIdx,
- jcampIdx,
- onPecker,
- sourceHint,
-});
+const restoreSweepExtent = (payload) => (
+ {
+ type: UI.SWEEP.SELECT_ZOOMIN,
+ payload,
+ }
+);
+
+const clickUiTarget = (payload, onPeak, voltammetryPeakIdx, jcampIdx, onPecker, sourceHint) => {
+ const action = {
+ type: UI.CLICK_TARGET,
+ payload,
+ onPeak,
+ voltammetryPeakIdx: voltammetryPeakIdx ?? 0,
+ onPecker: onPecker ?? false,
+ sourceHint: sourceHint ?? null,
+ };
+ if (Number.isFinite(jcampIdx)) {
+ action.jcampIdx = jcampIdx;
+ }
+ return action;
+};
const displaySubViewerAt = (payload) => ({
type: UI.SUB_VIEWER.DISPLAY_VIEWER_AT,
@@ -75,6 +80,7 @@ export {
setUiSweepType,
selectUiSweep,
scrollUiWheel,
+ restoreSweepExtent,
clickUiTarget,
displaySubViewerAt,
};
diff --git a/src/app.js b/src/app.js
index 8017f46e..dba0eb8e 100644
--- a/src/app.js
+++ b/src/app.js
@@ -44,7 +44,7 @@ const SpectraEditor = ({
entity, others, cLabel, xLabel, yLabel,
operations, forecast, molSvg, editorOnly, descriptions, exactMass,
canChangeDescription, onDescriptionChanged,
- multiEntities, multiMolSvgs, entityFileNames, userManualLink,
+ multiEntities, multiMolSvgs, entityFileNames, userManualLink, curveIdx, sweepExtent,
onLcmsPageRequest,
}) => (
@@ -52,6 +52,8 @@ const SpectraEditor = ({
{
- hideCmdAnaViewerSt
+ (hideCmdAnaViewerSt || disableCmdAnaViewerSt)
? null
: (
Analysis Viewer}>
-
-
-
-
-
+
+
+
)
}
diff --git a/src/components/cmd_bar/03_peak.js b/src/components/cmd_bar/03_peak.js
index aa219869..921448f9 100644
--- a/src/components/cmd_bar/03_peak.js
+++ b/src/components/cmd_bar/03_peak.js
@@ -50,6 +50,15 @@ const Peak = ({
clearAllPeaksAct({ curveIdx, dataPeaks });
}
};
+ const showAddPeak = !disableAddPeakSt;
+ const showRmPeak = !disableRmPeakSt;
+ const showSetRef = !disableSetRefSt;
+ const showClearAll = !disableRmPeakSt;
+
+ if (!showAddPeak && !showRmPeak && !showSetRef && !showClearAll) {
+ return null;
+ }
+
if (isHandleMaxAndMinPeaksSt) {
const { spectraList } = cyclicVoltaState;
const spectra = spectraList[curveIdx];
@@ -68,48 +77,58 @@ const Peak = ({
return (
- Add Peak}>
-
-
- P+
-
-
-
- Remove Peak}>
-
- Add Peak}>
+
+
+ P+
+
+
+
+ ) : null
+ }
+ {
+ showRmPeak ? (
+ Remove Peak}>
+
+
+ P-
+
+
+
+ ) : null
+ }
+ {
+ showClearAll ? (
+
- P-
-
-
-
-
- P
- x
-
+ P
+ x
+
+ ) : null
+ }
{
- !disableSetRefSt ? (
+ showSetRef ? (
Set Reference}>
diff --git a/src/components/cmd_bar/04_integration.js b/src/components/cmd_bar/04_integration.js
index 679a86da..8ae4f84c 100644
--- a/src/components/cmd_bar/04_integration.js
+++ b/src/components/cmd_bar/04_integration.js
@@ -55,7 +55,7 @@ const styles = () => (
const iconSize = '16px';
const setFactor = (
- classes, isDisable, integrationSt, setIntegrationFkrAct, curveIdx,
+ classes, integrationSt, setIntegrationFkrAct, curveIdx,
) => {
const onFactorChanged = (e) => {
e.target.blur();
@@ -83,7 +83,6 @@ const setFactor = (
return (
Add Integration}>
@@ -154,13 +157,12 @@ const Integration = ({
'btn-add-inter',
)
}
- disabled={isDisableSt}
onClick={onSweepIntegtAdd}
>
{
@@ -180,46 +182,38 @@ const Integration = ({
'btn-remove-inter',
)
}
- disabled={isDisableSt}
onClick={onSweepIntegtRm}
>
-
- {
- ignoreRef
- ? null
- : (
- Set Integration Reference}>
-
-
-
-
-
-
- )
- }
+ Set Integration Reference}>
+
+
+
+
+
+
{
showIntegSplitToolsSt
? (
@@ -233,13 +227,12 @@ const Integration = ({
'btn-split-inter',
)
}
- disabled={isDisableSt}
onClick={onSweepIntegtSplit}
>
{
@@ -259,13 +252,12 @@ const Integration = ({
'btn-visual-split-inter',
)
}
- disabled={isDisableSt}
onClick={onSweepIntegtVisualSplit}
>
{
@@ -283,7 +275,7 @@ const Integration = ({
{
!ignoreRef
? setFactor(
- classes, isDisableSt, integrationSt, setIntegrationFkrAct, curveIdx,
+ classes, integrationSt, setIntegrationFkrAct, curveIdx,
)
: null
}
@@ -294,7 +286,7 @@ const Integration = ({
x
diff --git a/src/components/cmd_bar/05_multiplicity.js b/src/components/cmd_bar/05_multiplicity.js
index fca449f7..f7a4a41f 100644
--- a/src/components/cmd_bar/05_multiplicity.js
+++ b/src/components/cmd_bar/05_multiplicity.js
@@ -27,8 +27,8 @@ const styles = () => (
);
const Multiplicity = ({
- classes, isFocusAddMpySt, disableAddMpySt, isFocusRmMpySt, disableRmMpySt,
- isFocusAddPeakSt, isFocusRmPeakSt, disableMpyPeakSt,
+ classes, isFocusAddMpySt, disableAddMpySt, isFocusRmMpySt,
+ isFocusAddPeakSt, isFocusRmPeakSt,
setUiSweepTypeAct, clearMpyAllAct, curveSt,
}) => {
const onSweepMutAdd = () => setUiSweepTypeAct(LIST_UI_SWEEP_TYPE.MULTIPLICITY_SWEEP_ADD);
@@ -38,6 +38,10 @@ const Multiplicity = ({
const { curveIdx } = curveSt;
const onClearAll = () => clearMpyAllAct({ curveIdx });
+ if (disableAddMpySt) {
+ return null;
+ }
+
return (
Add Multiplicity}>
@@ -49,7 +53,6 @@ const Multiplicity = ({
'btn-sv-bar-addmpy',
)
}
- disabled={disableAddMpySt}
onClick={onSweepMutAdd}
>
J+
@@ -65,7 +68,6 @@ const Multiplicity = ({
'btn-sv-bar-rmmpy',
)
}
- disabled={disableRmMpySt}
onClick={onOneMutAdd}
>
J-
@@ -81,7 +83,6 @@ const Multiplicity = ({
'btn-sv-bar-addpeakmpy',
)
}
- disabled={disableMpyPeakSt}
onClick={onPeakMutAdd}
>
JP+
@@ -97,25 +98,19 @@ const Multiplicity = ({
'btn-sv-bar-rmpeakmpy',
)
}
- disabled={disableMpyPeakSt}
onClick={onPeakMutRm}
>
JP-
- {
- disableAddMpySt ? null
- : // eslint-disable-line
- (
-
- Jx
-
- )
- }
+
+ Jx
+
);
};
diff --git a/src/components/cmd_bar/07_pecker.js b/src/components/cmd_bar/07_pecker.js
index 4b8cf4ee..3959911c 100644
--- a/src/components/cmd_bar/07_pecker.js
+++ b/src/components/cmd_bar/07_pecker.js
@@ -97,68 +97,69 @@ const Pecker = ({
hasRefPeaks = hasRefPeak;
}
+ if (Cfg.hidePanelCyclicVolta(layoutSt)) {
+ return null;
+ }
+
return (
- (!Cfg.hidePanelCyclicVolta(layoutSt)) ? (
-
- Add Pecker}>
-
-
-
- I
- λ0
- +
-
-
-
-
- Remove Pecker}>
-
-
-
- I
- λ0
- -
-
-
-
-
- {
- setRef(classes, cyclicVotaSt, curveIdx, setCylicVoltaRefFactorAct)
- }
- {hasRefPeaks ? 'Set Reference' : 'Set Shift'}}>
-
-
-
-
-
-
-
- )
- : ()
+
+ Add Pecker}>
+
+
+
+ I
+ λ0
+ +
+
+
+
+
+ Remove Pecker}>
+
+
+
+ I
+ λ0
+ -
+
+
+
+
+ {
+ setRef(classes, cyclicVotaSt, curveIdx, setCylicVoltaRefFactorAct)
+ }
+ {hasRefPeaks ? 'Set Reference' : 'Set Shift'}}>
+
+
+
+
+
+
+
);
};
diff --git a/src/components/cmd_bar/index.js b/src/components/cmd_bar/index.js
index 450c109d..f4d98ee0 100644
--- a/src/components/cmd_bar/index.js
+++ b/src/components/cmd_bar/index.js
@@ -23,6 +23,7 @@ import ChangeAxes from './r08_change_axes';
import Detector from './r09_detector';
import CvDensityControls from './r10_cv_density';
import Format from '../../helpers/format';
+import Cfg from '../../helpers/cfg';
const styles = () => (
Object.assign(
@@ -71,6 +72,8 @@ const CmdBar = ({
prependLcMsToolbar,
}) => {
const isCvLayout = Format.isCyclicVoltaLayout(layoutSt);
+ const hideIntegration = isCvLayout || Cfg.btnCmdIntg(layoutSt);
+ const hideMultiplicity = isCvLayout || Cfg.btnCmdMpy(layoutSt);
const rightCluster = (
<>
@@ -117,8 +120,8 @@ const CmdBar = ({
- {isCvLayout ? null : }
- {isCvLayout ? null : }
+ {hideIntegration ? null : }
+ {hideMultiplicity ? null : }
>
)
diff --git a/src/components/cmd_bar/r03_threshold.js b/src/components/cmd_bar/r03_threshold.js
index 77b49a19..bca9be2b 100644
--- a/src/components/cmd_bar/r03_threshold.js
+++ b/src/components/cmd_bar/r03_threshold.js
@@ -102,6 +102,9 @@ const Threshold = ({
} else {
thresVal = thresValSt || (feature ? feature.thresRef : hplcMsSt?.threshold?.value);
}
+ const { curveIdx } = curveSt;
+ const onResetThreshold = () => resetThresholdValueAct({ value: false, curveIdx });
+ const onToggleThreshold = () => toggleThresholdIsEditAct({ curveIdx });
return (
@@ -115,7 +118,7 @@ const Threshold = ({
)
}
disabled={Cfg.btnCmdThres(thresVal)}
- onClick={resetThresholdValueAct}
+ onClick={onResetThreshold}
>
@@ -134,7 +137,7 @@ const Threshold = ({
)
}
disabled={Cfg.btnCmdThres(thresVal)}
- onClick={toggleThresholdIsEditAct}
+ onClick={onToggleThreshold}
>
{ restoreIcon(classes, hasEdit, isEditSt) }
diff --git a/src/components/cmd_bar/r05_submit_btn.js b/src/components/cmd_bar/r05_submit_btn.js
index 428b031c..f864a10a 100644
--- a/src/components/cmd_bar/r05_submit_btn.js
+++ b/src/components/cmd_bar/r05_submit_btn.js
@@ -22,6 +22,7 @@ import {
getLcmsMzPageData,
} from '../../helpers/extractPeaksEdit';
import Format from '../../helpers/format';
+import { shiftEntryAtIndex, listEntryAtIndex } from '../../helpers/shift';
const styles = () => (
Object.assign(
@@ -97,9 +98,20 @@ const resolveLcmsIntegrationsExportForSubmit = (analysis, hplcMsSt) => {
return 'percent';
};
-const pickFromList = (list, index, fallback = null) => (
- Array.isArray(list) && list[index] !== undefined ? list[index] : fallback
-);
+const emptyIntegration = {
+ stack: [],
+ refArea: 1,
+ refFactor: 1,
+ shift: 0,
+ edited: false,
+};
+
+const emptyMultiplicity = {
+ stack: [],
+ shift: 0,
+ smExtext: false,
+ edited: false,
+};
const hasBoolean = (value) => typeof value === 'boolean';
@@ -142,9 +154,13 @@ const buildSpectrumPayload = ({
);
const scan = Convert2Scan(feature, scanSt);
const thres = Convert2Thres(feature, threshold);
- const shift = pickFromList(shiftSt?.shifts, curveIdx, shiftSt);
- const integration = pickFromList(integrationSt?.integrations, curveIdx, integrationSt);
- const multiplicity = pickFromList(multiplicitySt?.multiplicities, curveIdx, multiplicitySt);
+ const shift = shiftEntryAtIndex(shiftSt, curveIdx);
+ const integration = listEntryAtIndex(
+ integrationSt?.integrations, curveIdx, emptyIntegration,
+ );
+ const multiplicity = listEntryAtIndex(
+ multiplicitySt?.multiplicities, curveIdx, emptyMultiplicity,
+ );
const { xLabel, yLabel } = resolveAxisLabels(
feature?.xUnit,
feature?.yUnit,
@@ -172,6 +188,7 @@ const buildSpectrumPayload = ({
return {
peaks: peaksEdit,
layout: layoutSt,
+ xUnit: xLabel,
shift,
scan,
thres,
@@ -187,6 +204,7 @@ const buildSpectrumPayload = ({
axesUnitsSt,
detectorSt,
dscMetaData,
+ feature,
...optionalBooleanFlags,
};
};
@@ -196,7 +214,7 @@ const onClickCb = (
layoutSt, shiftSt, analysis, decimalSt,
integrationSt, multiplicitySt, waveLengthSt,
cyclicvoltaSt, curveSt, axesUnitsSt, detectorSt, dscMetaData,
- curveList, editPeakSt, thresList, scanSt, feature, hplcMsSt,
+ curveList, editPeakSt, thresList, scanSt, feature, hplcMsSt, sweepExtentSt,
) => (
() => {
const defaultCurves = feature ? [{ feature }] : [];
@@ -255,7 +273,10 @@ const onClickCb = (
}
return spectrumPayload;
});
+ const selectedIdx = Number.isFinite(curveSt?.curveIdx) ? curveSt.curveIdx : 0;
+ const selectedSpectrumPayload = spectraList[selectedIdx] || spectraList[0] || {};
const payload = {
+ ...selectedSpectrumPayload,
spectra_list: spectraList,
};
if (lcmsGlobalFields) {
@@ -264,6 +285,9 @@ const onClickCb = (
if (Number.isFinite(curveSt?.curveIdx)) {
payload.curveSt = { curveIdx: curveSt.curveIdx };
}
+ if (sweepExtentSt?.xExtent || sweepExtentSt?.yExtent) {
+ payload.sweepExtent = sweepExtentSt;
+ }
operationValue(payload);
}
);
@@ -275,6 +299,8 @@ const BtnSubmit = ({
waveLengthSt, cyclicvoltaSt, curveSt, curveList, axesUnitsSt, detectorSt,
metaSt,
hplcMsSt,
+ sweepExtentSt,
+ disabled, className, children,
}) => {
// const disBtn = peaksEdit.length === 0 || statusSt.btnSubmit || disabled;
const { dscMetaData } = metaSt;
@@ -303,23 +329,25 @@ const BtnSubmit = ({
if (!operation) return null;
return (
- Submit}>
+ {operation.name || 'Submit'}}>
-
+ {children || }
);
@@ -344,6 +372,7 @@ const mapStateToProps = (state, props) => ( // eslint-disable-line
detectorSt: state.detector,
metaSt: state.meta,
hplcMsSt: state.hplcMs,
+ sweepExtentSt: state.ui.sweepExtent,
}
);
@@ -375,6 +404,10 @@ BtnSubmit.propTypes = {
detectorSt: PropTypes.object.isRequired,
metaSt: PropTypes.object.isRequired,
hplcMsSt: PropTypes.object,
+ sweepExtentSt: PropTypes.object,
+ disabled: PropTypes.bool,
+ className: PropTypes.string,
+ children: PropTypes.node,
};
BtnSubmit.defaultProps = {
diff --git a/src/components/cmd_bar/r07_wavelength_btn.js b/src/components/cmd_bar/r07_wavelength_btn.js
index ebdabc32..a835245b 100644
--- a/src/components/cmd_bar/r07_wavelength_btn.js
+++ b/src/components/cmd_bar/r07_wavelength_btn.js
@@ -31,9 +31,7 @@ const styles = () => (
const wavelengthSelect = (classes, waveLengthSt, layoutSt, updateWavelengthAct) => {
if (!Format.isXRDLayout(layoutSt)) {
- return (
-
- );
+ return null;
}
const onChange = (e) => updateWavelengthAct(e.target.value);
@@ -72,11 +70,14 @@ const wavelengthSelect = (classes, waveLengthSt, layoutSt, updateWavelengthAct)
const Wavelength = ({
classes, waveLengthSt, layoutSt, updateWavelengthAct,
-}) => (
-
- { wavelengthSelect(classes, waveLengthSt, layoutSt, updateWavelengthAct) }
-
-);
+}) => {
+ if (!Format.isXRDLayout(layoutSt)) return null;
+ return (
+
+ { wavelengthSelect(classes, waveLengthSt, layoutSt, updateWavelengthAct) }
+
+ );
+};
const mapStateToProps = (state, props) => ( // eslint-disable-line
{
diff --git a/src/components/cmd_bar/r08_change_axes.js b/src/components/cmd_bar/r08_change_axes.js
index 6ceb4199..62a04537 100644
--- a/src/components/cmd_bar/r08_change_axes.js
+++ b/src/components/cmd_bar/r08_change_axes.js
@@ -124,9 +124,7 @@ const axisY = (classes, layoutSt, axesUnitsSt, updateYAxisAct, curveSt) => {
const showSelect = (classes, layoutSt, curveSt, axesUnitsSt, updateXAxisAct, updateYAxisAct) => {
if (!listLayoutToShow.includes(layoutSt)) {
- return (
-
- );
+ return null;
}
return (
@@ -151,6 +149,8 @@ const ChangeAxes = ({
}
}, [layoutSt, axes, curveIdx, updateYAxisAct]);
+ if (!listLayoutToShow.includes(layoutSt)) return null;
+
return (
{ showSelect(classes, layoutSt, curveSt, axesUnitsSt, updateXAxisAct, updateYAxisAct) }
diff --git a/src/components/cmd_bar/r09_detector.js b/src/components/cmd_bar/r09_detector.js
index 2ab696c9..d2116b5d 100644
--- a/src/components/cmd_bar/r09_detector.js
+++ b/src/components/cmd_bar/r09_detector.js
@@ -31,9 +31,7 @@ const styles = () => (
const detectorSelect = (classes, detectorSt, curveSt, layoutSt, updateDetectorAct) => {
if (!Format.isSECLayout(layoutSt)) {
- return (
-
- );
+ return null;
}
const { curveIdx } = curveSt;
@@ -85,11 +83,14 @@ const detectorSelect = (classes, detectorSt, curveSt, layoutSt, updateDetectorAc
const Detector = ({
classes, detectorSt, curveSt, layoutSt, updateDetectorAct,
-}) => (
-
- { detectorSelect(classes, detectorSt, curveSt, layoutSt, updateDetectorAct) }
-
-);
+}) => {
+ if (!Format.isSECLayout(layoutSt)) return null;
+ return (
+
+ { detectorSelect(classes, detectorSt, curveSt, layoutSt, updateDetectorAct) }
+
+ );
+};
const mapStateToProps = (state, _props) => ( // eslint-disable-line
{
diff --git a/src/components/cmd_bar/r10_cv_density.js b/src/components/cmd_bar/r10_cv_density.js
index 12218bb1..a74ddd4e 100644
--- a/src/components/cmd_bar/r10_cv_density.js
+++ b/src/components/cmd_bar/r10_cv_density.js
@@ -42,7 +42,7 @@ const CvDensityControls = ({
classes, layoutSt, areaValue, areaUnit, useCurrentDensity,
setAreaValueAct, setAreaUnitAct, toggleDensityAct,
}) => {
- if (layoutSt !== LIST_LAYOUT.CYCLIC_VOLTAMMETRY) return ;
+ if (layoutSt !== LIST_LAYOUT.CYCLIC_VOLTAMMETRY) return null;
const handleAreaChange = (e) => {
const raw = e.target.value;
diff --git a/src/components/common/draw.js b/src/components/common/draw.js
index c8478546..b1861001 100644
--- a/src/components/common/draw.js
+++ b/src/components/common/draw.js
@@ -22,7 +22,7 @@ const drawDisplay = (klass, isHidden) => {
}
};
-const drawDestroy = (klass) => d3.select(`${klass} > *`).remove();
+const drawDestroy = (klass) => d3.select(klass).selectAll('*').remove();
const drawArrowOnCurve = (klass, isHidden) => {
if (isHidden) {
diff --git a/src/components/d3_line/line_focus.js b/src/components/d3_line/line_focus.js
index e819583e..af3b6c47 100644
--- a/src/components/d3_line/line_focus.js
+++ b/src/components/d3_line/line_focus.js
@@ -307,6 +307,12 @@ class LineFocus {
mpp.exit()
.attr('class', 'exit')
.remove();
+ const clearPeakLabels = () => {
+ const bpTxt = this.tags.bpTxt.selectAll('text').data([]);
+ bpTxt.exit()
+ .attr('class', 'exit')
+ .remove();
+ };
const linePath = [
{ x: -0.5, y: 10 },
@@ -367,6 +373,8 @@ class LineFocus {
.text((d) => d.x.toFixed(2))
.attr('transform', (d) => `translate(${xt(d.x)}, ${yt(d.y) - 25})`)
.on('click', (event, d) => this.onClickTarget(event, d));
+ } else {
+ clearPeakLabels();
}
}
@@ -376,8 +384,35 @@ class LineFocus {
} = this.shouldUpdate;
if (sameXY && sameLySt && sameItSt && sameData) return;
+ const clearIntegralPaths = () => {
+ const empty = [];
+ const igbp = this.tags.igbPath.selectAll('path').data(empty);
+ igbp.exit()
+ .attr('class', 'exit')
+ .remove();
+ const igcp = this.tags.igcPath.selectAll('path').data(empty);
+ igcp.exit()
+ .attr('class', 'exit')
+ .remove();
+ const igtp = this.tags.igtPath.selectAll('text').data(empty);
+ igtp.exit()
+ .attr('class', 'exit')
+ .remove();
+ };
+ const clearAUC = () => {
+ const auc = this.tags.aucPath.selectAll('path').data([]);
+ auc.exit()
+ .attr('class', 'exit')
+ .remove();
+ };
+
const { selectedIdx, integrations } = integrationState;
const selectedIntegration = integrations[selectedIdx];
+ if (selectedIntegration === false || selectedIntegration === undefined) {
+ clearIntegralPaths();
+ clearAUC();
+ return;
+ }
const {
stack, refArea, refFactor, shift,
@@ -406,19 +441,16 @@ class LineFocus {
.remove();
if (itgs.length === 0 || isDisable) {
- // remove drawn area under curve
- const auc = this.tags.aucPath.selectAll('path').data(stack);
- auc.exit()
- .attr('class', 'exit')
- .remove();
- auc.merge(auc);
- this.drawVisualSplitLines(showIntegSplit ? itgs : [], shift, ignoreRef);
+ clearIntegralPaths();
+ clearAUC();
return;
}
if (ignoreRef) {
+ clearIntegralPaths();
this.drawAUC(stack, shift);
} else {
+ clearAUC();
// rescale for zoom
const { xt } = TfRescale(this);
@@ -556,16 +588,16 @@ class LineFocus {
const { selectedIdx, multiplicities = [] } = mtplySt || {};
const selectedMulti = multiplicities[selectedIdx] || {};
- const {
- stack = [], smExtext = false, shift = 0,
- } = selectedMulti;
+ const isDisable = Cfg.btnCmdMpy(this.layout);
+ const hasMpy = !isDisable && selectedMulti?.stack?.length > 0;
+ const mpys = hasMpy ? selectedMulti.stack : [];
+ const smExtext = hasMpy ? selectedMulti.smExtext : false;
+ const shift = hasMpy ? selectedMulti.shift : 0;
const hasValidExtent = (extent) => (
extent
&& Number.isFinite(extent.xL)
&& Number.isFinite(extent.xU)
);
- const mpys = stack.filter((m) => hasValidExtent(m?.xExtent));
- const isDisable = Cfg.btnCmdMpy(this.layout);
if (mpys.length === 0 || isDisable) return;
const activeExtent = hasValidExtent(smExtext) ? smExtext : mpys[0].xExtent;
// rescale for zoom
diff --git a/src/components/d3_multi/index.js b/src/components/d3_multi/index.js
index 1aa27a4a..0b74654e 100644
--- a/src/components/d3_multi/index.js
+++ b/src/components/d3_multi/index.js
@@ -29,6 +29,26 @@ import {
const W = Math.round(window.innerWidth * 0.90 * 9 / 12); // ROI
const H = Math.round(window.innerHeight * 0.90 * 0.85); // ROI
+const buildResetPayload = (feature, curveSt) => (
+ { ...feature, curveIdx: curveSt.curveIdx }
+);
+
+const hasActiveZoom = (sweepExtentSt) => {
+ if (!sweepExtentSt) return false;
+ return !!(sweepExtentSt.xExtent || sweepExtentSt.yExtent);
+};
+
+const canSkipReset = (sweepExtentSt, layoutSt, feature) => (
+ hasActiveZoom(sweepExtentSt) && layoutSt === feature?.operation?.layout
+);
+
+const isSameMultiComparison = (oldEntities, newEntities) => (
+ Array.isArray(oldEntities)
+ && Array.isArray(newEntities)
+ && oldEntities.length > 0
+ && oldEntities.length === newEntities.length
+);
+
class ViewerMulti extends React.Component {
constructor(props) {
super(props);
@@ -70,7 +90,7 @@ class ViewerMulti extends React.Component {
seed, peak, cLabel, xLabel, yLabel,
tTrEndPts, tSfPeaks, editPeakSt, layoutSt,
sweepExtentSt, isUiAddIntgSt, isUiSplitIntgSt, isUiVisualSplitIntgSt, isUiNoBrushSt,
- isHidden, cyclicvoltaSt,
+ isHidden, cyclicvoltaSt, shiftSt,
integrationSt, mtplySt, axesUnitsSt,
uiSt,
} = this.props;
@@ -118,6 +138,7 @@ class ViewerMulti extends React.Component {
isUiVisualSplitIntgSt,
isUiNoBrushSt,
cyclicvoltaSt,
+ shiftSt,
integrationSt,
mtplySt,
uiSt,
@@ -215,10 +236,13 @@ class ViewerMulti extends React.Component {
}
normChange(prevProps) {
- const { feature, resetAllAct, entities } = this.props;
+ const {
+ feature, resetAllAct, entities, curveSt,
+ } = this.props;
const oldEntities = prevProps.entities;
- if (oldEntities !== entities) {
- resetAllAct(feature);
+ if (oldEntities !== entities
+ && !isSameMultiComparison(oldEntities, entities)) {
+ resetAllAct(buildResetPayload(feature, curveSt));
}
}
@@ -246,7 +270,7 @@ class ViewerMulti extends React.Component {
seed, peak, cLabel, feature,
tTrEndPts, tSfPeaks, editPeakSt, layoutSt,
sweepExtentSt, isUiAddIntgSt, isUiSplitIntgSt, isUiVisualSplitIntgSt, isUiNoBrushSt,
- isHidden, resetAllAct, cyclicvoltaSt,
+ isHidden, resetAllAct, cyclicvoltaSt, shiftSt,
integrationSt, mtplySt, uiSt,
} = props;
@@ -254,8 +278,8 @@ class ViewerMulti extends React.Component {
this.currentSize = size;
drawDestroy(this.rootKlass);
- if (shouldReset) {
- resetAllAct(feature);
+ if (shouldReset && !canSkipReset(sweepExtentSt, layoutSt, feature)) {
+ resetAllAct(buildResetPayload(feature, curveSt));
}
const { xxLabel, yyLabel } = this.resolveAxisLabels(props);
@@ -278,6 +302,7 @@ class ViewerMulti extends React.Component {
isUiVisualSplitIntgSt,
isUiNoBrushSt,
cyclicvoltaSt,
+ shiftSt,
integrationSt,
mtplySt,
uiSt,
@@ -318,6 +343,7 @@ const mapStateToProps = (state, props) => (
&& state.ui.sweepType === LIST_UI_SWEEP_TYPE.INTEGRATION_VISUAL_SPLIT,
isUiNoBrushSt: LIST_NON_BRUSH_TYPES.indexOf(state.ui.sweepType) < 0,
cyclicvoltaSt: state.cyclicvolta,
+ shiftSt: state.shift,
maxminPeakSt: Feature2MaxMinPeak(state, props),
integrationSt: state.integration.present,
mtplySt: state.multiplicity.present,
@@ -369,6 +395,7 @@ ViewerMulti.propTypes = {
removeVisualSplitLineAct: PropTypes.func.isRequired,
isHidden: PropTypes.bool,
cyclicvoltaSt: PropTypes.object.isRequired,
+ shiftSt: PropTypes.object.isRequired,
maxminPeakSt: PropTypes.object,
addNewCylicVoltaPairPeakAct: PropTypes.func.isRequired,
addCylicVoltaMaxPeakAct: PropTypes.func.isRequired,
diff --git a/src/components/d3_multi/multi_focus.js b/src/components/d3_multi/multi_focus.js
index a1d20da8..1bd925f1 100644
--- a/src/components/d3_multi/multi_focus.js
+++ b/src/components/d3_multi/multi_focus.js
@@ -24,6 +24,7 @@ import Format from '../../helpers/format';
import {
GetCyclicVoltaPreviousShift, convertTopic,
} from '../../helpers/chem';
+import { shiftOffsetAtIndex } from '../../helpers/shift';
import Cfg from '../../helpers/cfg';
import { itgIdTag, mpyIdTag } from '../../helpers/focus';
import {
@@ -126,6 +127,7 @@ class MultiFocus {
const {
prevXt, prevYt, prevEpSt, prevLySt,
prevTePt, prevDtPk, prevSfPk, prevData, prevYFactor,
+ prevJcampIdx,
} = this.shouldUpdate;
const { xt, yt } = TfRescale(this);
const sameXY = xt(1.1) === prevXt && prevYt === yt(1.1);
@@ -142,12 +144,13 @@ class MultiFocus {
);
const sameData = prevData === this.data.length;
const sameYFactor = prevYFactor === this.yTransformFactor;
+ const sameJcampIdx = prevJcampIdx === this.jcampIdx;
this.shouldUpdate = Object.assign(
{},
this.shouldUpdate,
{
sameXY, sameEpSt, sameLySt, // eslint-disable-line
- sameTePt, sameDtPk, sameSfPk, sameData, sameYFactor, // eslint-disable-line
+ sameTePt, sameDtPk, sameSfPk, sameData, sameYFactor, sameJcampIdx, // eslint-disable-line
},
);
}
@@ -162,12 +165,13 @@ class MultiFocus {
const prevData = this.data.length;
const prevLySt = this.layout;
const prevYFactor = this.yTransformFactor;
+ const prevJcampIdx = this.jcampIdx;
this.shouldUpdate = Object.assign(
{},
this.shouldUpdate,
{
prevXt, prevYt, prevEpSt, prevLySt, // eslint-disable-line
- prevTePt, prevDtPk, prevSfPk, prevData, prevYFactor, // eslint-disable-line
+ prevTePt, prevDtPk, prevSfPk, prevData, prevYFactor, prevJcampIdx, // eslint-disable-line
},
);
}
@@ -198,7 +202,7 @@ class MultiFocus {
return y * this.yTransformFactor;
}
- setDataParams(filterSeed, peaks, tTrEndPts, tSfPeaks, layout, cyclicvoltaSt, jcampIdx = 0) {
+ setDataParams(filterSeed, peaks, tTrEndPts, tSfPeaks, layout, cyclicvoltaSt, shiftSt, jcampIdx = 0) {
this.data = [];
this.otherLineData = [];
let filterSubLayoutValue = null;
@@ -208,7 +212,9 @@ class MultiFocus {
this.entities.forEach((entry, idx) => {
const { topic, feature, color } = entry;
- const offset = GetCyclicVoltaPreviousShift(cyclicvoltaSt, jcampIdx);
+ const offset = Format.isCyclicVoltaLayout(layout)
+ ? GetCyclicVoltaPreviousShift(cyclicvoltaSt, idx)
+ : shiftOffsetAtIndex(shiftSt, idx);
let currData = convertTopic(topic, layout, feature, offset);
if (idx === jcampIdx) {
if (!Format.isCyclicVoltaLayout(layout)) {
@@ -426,11 +432,11 @@ class MultiFocus {
drawPeaks(editPeakSt) {
const {
- sameXY, sameEpSt, sameDtPk, sameSfPk,
+ sameXY, sameEpSt, sameDtPk, sameSfPk, sameJcampIdx,
} = this.shouldUpdate;
if (!Format.isCyclicVoltaLayout(this.layout)
- && sameXY && sameEpSt && sameDtPk && sameSfPk) return;
+ && sameXY && sameEpSt && sameDtPk && sameSfPk && sameJcampIdx) return;
// rescale for zoom
const { xt, yt } = TfRescale(this);
@@ -454,6 +460,12 @@ class MultiFocus {
mpp.exit()
.attr('class', 'exit')
.remove();
+ const clearPeakLabels = () => {
+ const bpTxt = this.tags.bpTxt.selectAll('text').data([]);
+ bpTxt.exit()
+ .attr('class', 'exit')
+ .remove();
+ };
const linePath = [
{ x: -0.5, y: 10 },
@@ -528,6 +540,8 @@ class MultiFocus {
.text((d) => d.x.toFixed(2))
.attr('transform', (d) => `translate(${xt(d.x)}, ${yt(d.y) - 25})`)
.on('click', (event, d) => this.onClickTarget(event, d));
+ } else {
+ clearPeakLabels();
}
mpp.attr('fill', (_, index) => {
@@ -541,11 +555,11 @@ class MultiFocus {
drawPeckers() {
const {
- sameXY, sameEpSt, sameDtPk, sameSfPk,
+ sameXY, sameEpSt, sameDtPk, sameSfPk, sameJcampIdx,
} = this.shouldUpdate;
if (!Format.isCyclicVoltaLayout(this.layout) && sameXY
- && sameEpSt && sameDtPk && sameSfPk) return;
+ && sameEpSt && sameDtPk && sameSfPk && sameJcampIdx) return;
// rescale for zoom
const { xt, yt } = TfRescale(this);
@@ -598,31 +612,37 @@ class MultiFocus {
drawInteg(integrationState) {
const {
- sameXY, sameLySt, sameItSt, sameData,
+ sameXY, sameLySt, sameItSt, sameData, sameJcampIdx,
} = this.shouldUpdate;
- if (sameXY && sameLySt && sameItSt && sameData) return;
+ if (sameXY && sameLySt && sameItSt && sameData && sameJcampIdx) return;
- const { integrations } = integrationState;
- const selectedIntegration = integrations[this.jcampIdx];
- if (selectedIntegration === false || selectedIntegration === undefined) {
- Object.assign(this, {
- integrationSplitTargets: { stack: [], shift: 0, ignoreRef: false },
- });
- const itgs = [];
- const igbp = this.tags.igbPath.selectAll('path').data(itgs);
+ const clearIntegralPaths = () => {
+ const empty = [];
+ const igbp = this.tags.igbPath.selectAll('path').data(empty);
igbp.exit()
.attr('class', 'exit')
.remove();
- const igcp = this.tags.igcPath.selectAll('path').data(itgs);
+ const igcp = this.tags.igcPath.selectAll('path').data(empty);
igcp.exit()
.attr('class', 'exit')
.remove();
-
- const igtp = this.tags.igtPath.selectAll('text').data(itgs);
+ const igtp = this.tags.igtPath.selectAll('text').data(empty);
igtp.exit()
.attr('class', 'exit')
.remove();
- this.drawVisualSplitLines([], 0, false);
+ };
+ const clearAUC = () => {
+ const auc = this.tags.aucPath.selectAll('path').data([]);
+ auc.exit()
+ .attr('class', 'exit')
+ .remove();
+ };
+
+ const { integrations } = integrationState;
+ const selectedIntegration = integrations[this.jcampIdx];
+ if (selectedIntegration === false || selectedIntegration === undefined) {
+ clearIntegralPaths();
+ clearAUC();
return;
}
@@ -653,19 +673,16 @@ class MultiFocus {
.remove();
if (itgs.length === 0 || isDisable) {
- // remove drawn area under curve
- const auc = this.tags.aucPath.selectAll('path').data(stack);
- auc.exit()
- .attr('class', 'exit')
- .remove();
- auc.merge(auc);
- this.drawVisualSplitLines(showIntegSplit ? itgs : [], shift, ignoreRef);
+ clearIntegralPaths();
+ clearAUC();
return;
}
if (ignoreRef) {
+ clearIntegralPaths();
this.drawAUC(stack, shift);
} else {
+ clearAUC();
// rescale for zoom
const { xt } = TfRescale(this);
@@ -797,48 +814,24 @@ class MultiFocus {
}
drawMtply(mtplySt) {
- const { sameXY, sameLySt, sameMySt } = this.shouldUpdate;
- if (sameXY && sameLySt && sameMySt) return;
+ const {
+ sameXY, sameLySt, sameMySt, sameJcampIdx,
+ } = this.shouldUpdate;
+ if (sameXY && sameLySt && sameMySt && sameJcampIdx) return;
const { multiplicities } = mtplySt;
const selectedMulti = multiplicities[this.jcampIdx];
- if (selectedMulti === false || selectedMulti === undefined) {
- const mpys = [];
- const mpyb = this.tags.mpybPath.selectAll('path').data(mpys);
- mpyb.exit()
- .attr('class', 'exit')
- .remove();
- const mpyt1 = this.tags.mpyt1Path.selectAll('text').data(mpys);
- mpyt1.exit()
- .attr('class', 'exit')
- .remove();
- const mpyt2 = this.tags.mpyt2Path.selectAll('text').data(mpys);
- mpyt2.exit()
- .attr('class', 'exit')
- .remove();
- let mPeaks = mpys.map((m) => {
- const { peaks, xExtent } = m;
- return peaks.map((p) => Object.assign({}, p, { xExtent }));
- });
- mPeaks = [].concat(...mPeaks);
- const mpyp = this.tags.mpypPath.selectAll('path').data(mPeaks);
- mpyp.exit()
- .attr('class', 'exit')
- .remove();
- return;
- }
-
- const {
- stack = [], smExtext = false, shift = 0,
- } = selectedMulti || {};
+ const isDisable = Cfg.btnCmdMpy(this.layout);
+ const hasMpy = !isDisable && selectedMulti?.stack?.length > 0;
+ const mpys = hasMpy ? selectedMulti.stack : [];
+ const smExtext = hasMpy ? selectedMulti.smExtext : false;
+ const shift = hasMpy ? selectedMulti.shift : 0;
const hasValidExtent = (extent) => (
extent
&& Number.isFinite(extent.xL)
&& Number.isFinite(extent.xU)
);
- const mpys = stack.filter((m) => hasValidExtent(m?.xExtent));
- const isDisable = Cfg.btnCmdMpy(this.layout);
if (mpys.length === 0 || isDisable) return;
const activeExtent = hasValidExtent(smExtext) ? smExtext : mpys[0].xExtent;
// rescale for zoom
@@ -1077,7 +1070,7 @@ class MultiFocus {
filterSeed, filterPeak, tTrEndPts, tSfPeaks,
editPeakSt, layoutSt,
sweepExtentSt, isUiAddIntgSt, isUiSplitIntgSt, isUiVisualSplitIntgSt, isUiNoBrushSt,
- cyclicvoltaSt,
+ cyclicvoltaSt, shiftSt,
integrationSt, mtplySt, uiSt,
}) {
this.uiSt = uiSt;
@@ -1093,7 +1086,7 @@ class MultiFocus {
this.root = d3.select(this.rootKlass).selectAll('.focus-main');
this.scales = InitScale(this, this.reverseXAxis(layoutSt));
this.setTip();
- this.setDataParams(filterSeed, filterPeak, tTrEndPts, tSfPeaks, layoutSt, cyclicvoltaSt, jcampIdx);
+ this.setDataParams(filterSeed, filterPeak, tTrEndPts, tSfPeaks, layoutSt, cyclicvoltaSt, shiftSt, jcampIdx);
Object.assign(this, { isUiSplitIntgSt, isUiVisualSplitIntgSt });
if (!isUiSplitIntgSt && !isUiVisualSplitIntgSt) this.clearSplitPreview();
MountCompass(this);
@@ -1127,7 +1120,7 @@ class MultiFocus {
entities, curveSt,
filterSeed, filterPeak, tTrEndPts, tSfPeaks,
editPeakSt, layoutSt,
- sweepExtentSt, isUiAddIntgSt, isUiSplitIntgSt, isUiVisualSplitIntgSt, isUiNoBrushSt, cyclicvoltaSt,
+ sweepExtentSt, isUiAddIntgSt, isUiSplitIntgSt, isUiVisualSplitIntgSt, isUiNoBrushSt, cyclicvoltaSt, shiftSt,
integrationSt, mtplySt, uiSt,
}) {
this.uiSt = uiSt;
@@ -1140,7 +1133,7 @@ class MultiFocus {
this.isShowAllCurves = isShowAllCurve;
this.entities = entities;
- this.setDataParams(filterSeed, filterPeak, tTrEndPts, tSfPeaks, layoutSt, cyclicvoltaSt, jcampIdx);
+ this.setDataParams(filterSeed, filterPeak, tTrEndPts, tSfPeaks, layoutSt, cyclicvoltaSt, shiftSt, jcampIdx);
Object.assign(this, { isUiSplitIntgSt, isUiVisualSplitIntgSt });
if (!isUiSplitIntgSt && !isUiVisualSplitIntgSt) this.clearSplitPreview();
diff --git a/src/components/panel/graph_selection.js b/src/components/panel/graph_selection.js
index 60316157..c50842aa 100644
--- a/src/components/panel/graph_selection.js
+++ b/src/components/panel/graph_selection.js
@@ -20,36 +20,78 @@ const styles = () => ({
backgroundColor: '#eee',
height: 22,
},
- curve: {
+ curveItem: {
+ display: 'flex',
+ alignItems: 'center',
width: '100%',
- },
- line: {
- height: '2px',
- borderWidth: '0',
- margin: '0',
+ fontSize: '0.8em',
+ padding: '6px 8px',
+ margin: 0,
+ cursor: 'pointer',
},
curveDefault: {
backgroundColor: '#fff',
- fontSize: '0.8em',
- margin: '0',
- padding: '10px 2px 2px 10px',
- maxWidth: '95%',
- overflowWrap: 'anywhere',
},
curveSelected: {
- backgroundColor: '#2196f3',
- fontSize: '0.8em',
- color: '#fff',
- padding: '10px 2px 2px 10px',
- maxWidth: '95%',
+ backgroundColor: '#e0e0e0',
+ },
+ curveIndex: {
+ flexShrink: 0,
+ marginRight: '4px',
+ fontStyle: 'italic',
+ },
+ curveLabel: {
+ flexShrink: 0,
+ marginRight: '8px',
overflowWrap: 'anywhere',
},
+ colorBar: {
+ flex: 1,
+ height: '6px',
+ borderRadius: '1px',
+ minWidth: '24px',
+ alignSelf: 'center',
+ },
});
+const fallbackName = (entityFileNames, idx) => {
+ if (entityFileNames && idx < entityFileNames.length) {
+ return entityFileNames[idx];
+ }
+ return '';
+};
+
+const displayName = (spectra, idx, entityFileNames) => (
+ spectra?.title
+ || spectra?.feature?.title
+ || spectra?.spectrum?.title
+ || fallbackName(entityFileNames, idx)
+ || `Spectrum ${idx + 1}`
+);
+
+const renderCurveItem = (classes, item, curveIdx, onChange) => (
+ onChange(item.idx)}
+ className={classNames(
+ classes.curveItem,
+ item.idx === curveIdx ? classes.curveSelected : classes.curveDefault,
+ )}
+ >
+ {item.name}
+ {item.label !== '' ? {item.label} : null}
+
+
+);
+
const GraphSelectionPanel = ({
classes, curveSt,
entityFileNames, subLayoutsInfo, layoutSt,
- selectCurveAct, toggleShowAllCurveAct,
+ selectCurveAct, toggleShowAllCurveAct, expand, onExapnd,
}) => {
let subLayoutValues = [];
if (subLayoutsInfo) {
@@ -89,33 +131,37 @@ const GraphSelectionPanel = ({
let itemsSubLayout = [];
if (selectedSubLayout && subLayoutValues.length > 1) {
const subLayout = subLayoutsInfo?.[resolvedSelectedSubLayout];
- itemsSubLayout = Array.isArray(subLayout) ? subLayout.map((spectra, idx) => {
- const spectraIdx = spectra.curveIdx;
- const { color } = spectra;
- let filename = '';
- if (entityFileNames && spectraIdx < entityFileNames.length) {
- filename = entityFileNames[spectraIdx];
- }
- return {
- name: `${idx + 1}.`, idx: spectraIdx, color, filename,
- };
- }) : [];
+ try {
+ itemsSubLayout = Array.isArray(subLayout) ? subLayout.map((spectra, idx) => {
+ const spectraIdx = spectra.curveIdx;
+ const { color } = spectra;
+ return {
+ name: `${idx + 1}.`,
+ idx: spectraIdx,
+ color,
+ label: displayName(spectra, spectraIdx, entityFileNames),
+ };
+ }) : [];
+ } catch (e) {
+ console.log(e); //eslint-disable-line
+ }
}
const items = listCurves.map((spectra, idx) => {
const { color } = spectra;
- let filename = '';
- if (entityFileNames && idx < entityFileNames.length) {
- filename = entityFileNames[idx];
- }
return {
- name: `${idx + 1}.`, idx, color, filename,
+ name: `${idx + 1}.`,
+ idx,
+ color,
+ label: displayName(spectra, idx, entityFileNames),
};
});
return (
{
- itemsSubLayout.map((item) => (
- onChange(item.idx)}
- className={
- classNames((item.idx === curveIdx ? classes.curveSelected : classes.curveDefault)) // eslint-disable-line
- }
- >
-
- { item.name }
-
-
- {
- item.filename !== '' ? File: { item.filename } : null // eslint-disable-line
- }
-
-
-
- ))
+ itemsSubLayout.map((item) => renderCurveItem(classes, item, curveIdx, onChange))
}
+ ) : (
+
+ {
+ items.map((item) => renderCurveItem(classes, item, curveIdx, onChange))
+ }
+
)
- : (
-
- {
- items.map((item) => (
- onChange(item.idx)}
- className={
- classNames((item.idx === curveIdx ? classes.curveSelected : classes.curveDefault)) // eslint-disable-line
- }
- >
-
- { item.name }
-
-
- {
- item.filename !== '' ? File: { item.filename } : null // eslint-disable-line
- }
-
-
-
- ))
- }
-
- )
}
);
diff --git a/src/components/panel/index.js b/src/components/panel/index.js
index 7461dc40..dfdc79fb 100644
--- a/src/components/panel/index.js
+++ b/src/components/panel/index.js
@@ -47,7 +47,7 @@ class PanelViewer extends React.Component {
super(props);
this.state = {
- expand: 'info',
+ expand: ['info', 'graph'],
};
this.onToggleExpand = this.onToggleExpand.bind(this);
@@ -63,7 +63,9 @@ class PanelViewer extends React.Component {
onToggleExpand(input) {
const { expand } = this.state;
- const nextExpand = input === expand ? '' : input;
+ const nextExpand = expand.includes(input)
+ ? expand.filter((item) => item !== input)
+ : [...expand, input];
this.setState({ expand: nextExpand });
}
@@ -81,6 +83,7 @@ class PanelViewer extends React.Component {
const onExpandCompare = () => this.onToggleExpand('compare');
const onExpandCyclicVolta = () => this.onToggleExpand('cyclicvolta');
const onExpandGraphSelection = () => this.onToggleExpand('graph');
+ const isExpanded = (name) => expand.includes(name);
const { listCurves } = curveSt;
const curveCount = Array.isArray(listCurves) ? listCurves.length : 0;
const hideGraphSelection = curveCount <= 1 || Format.isLCMsLayout(layoutSt);
@@ -91,13 +94,13 @@ class PanelViewer extends React.Component {
- { hideGraphSelection ? null : }
+ { hideGraphSelection ? null : }
- { Cfg.hidePanelPeak(layoutSt) ? null : }
- { Cfg.hidePanelMpy(layoutSt) ? null : }
- { (Cfg.hidePanelCompare(layoutSt) || curveCount > 1) ? null : }
+ { Cfg.hidePanelPeak(layoutSt) ? null : }
+ { Cfg.hidePanelMpy(layoutSt) ? null : }
+ { (Cfg.hidePanelCompare(layoutSt) || !listCurves || listCurves.length > 1) ? null : }
{ (Cfg.hidePanelCyclicVolta(layoutSt) || hideCyclicVolta) ? null : (
diff --git a/src/components/panel/info.js b/src/components/panel/info.js
index 72bc74db..3a105c36 100644
--- a/src/components/panel/info.js
+++ b/src/components/panel/info.js
@@ -174,54 +174,6 @@ const handleDescriptionChanged = (content, delta, source, editor, onDescriptionC
onDescriptionChanged(normalizeQuillValue(content), delta, source, editor);
};
-const aucValue = (integration, hplcMsSt) => {
- const values = [];
- const stackIntegration = integration?.stack;
- if (Array.isArray(stackIntegration)) {
- let sumVal = 0.0;
- stackIntegration.forEach((inte) => {
- if (inte.absoluteArea) {
- sumVal += inte.absoluteArea;
- }
- });
- sumVal = sumVal.toFixed(2);
- stackIntegration.forEach((inte) => {
- if (inte.absoluteArea) {
- const areaVal = inte.absoluteArea.toFixed(2);
- const percent = (areaVal * 100 / sumVal).toFixed(2);
- const valStr = areaVal + " (" + percent + "%)"; // eslint-disable-line
- values.push(valStr);
- }
- });
- }
-
- const spectraList = hplcMsSt?.uvvis?.spectraList || [];
- const listWaveLength = hplcMsSt?.uvvis?.listWaveLength || [];
-
- spectraList.forEach((spectrum, idx) => {
- const wavelength = listWaveLength[idx];
- const integrations = spectrum?.integrations || [];
-
- if (integrations.length > 0) {
- const sumArea = integrations.reduce(
- (sum, integ) => sum + (integ.absoluteArea ?? integ.area ?? 0),
- 0,
- );
-
- const integrationStrings = integrations.map((integ) => {
- const rawArea = integ.absoluteArea ?? integ.area ?? 0;
- const areaVal = rawArea.toFixed(2);
- const percent = sumArea > 0 ? ((rawArea * 100) / sumArea).toFixed(2) : '0.00';
- return `${areaVal} (${percent}%)`;
- });
-
- values.push(`[${wavelength} nm]: ${integrationStrings.join(', ')}`);
- }
- });
-
- return values.join('\n');
-};
-
const SECData = ({
classes, layout, detector, secData,
}) => {
@@ -313,7 +265,7 @@ const InfoPanel = ({
classes, expand, feature, integration, editorOnly, molSvg, descriptions,
layoutSt, simulationSt, shiftSt, curveSt, exactMass,
onExpand, canChangeDescription, onDescriptionChanged, detectorSt,
- metaSt, updateDSCMetaDataAct, hplcMsSt, entities,
+ metaSt, updateDSCMetaDataAct, entities,
}) => {
if (!feature) return null;
const msExactMass = Format.isMsLayout(layoutSt) && exactMass
@@ -438,7 +390,7 @@ const InfoPanel = ({
- {aucValue(integration)}
+ {Format.formatHplcAucPanel(integration, feature)}
) : null
@@ -505,7 +457,7 @@ const InfoPanel = ({
marginBottom: '100px',
}}
>
- {aucValue(integration, hplcMsSt)
+ {Format.formatHplcAucPanel(integration, feature)
.split('\n')
.map((line, idx) => (
{line}
@@ -558,7 +510,6 @@ InfoPanel.propTypes = {
detectorSt: PropTypes.object.isRequired,
metaSt: PropTypes.object.isRequired,
updateDSCMetaDataAct: PropTypes.func.isRequired,
- hplcMsSt: PropTypes.object.isRequired,
entities: PropTypes.array,
};
diff --git a/src/helpers/chem.js b/src/helpers/chem.js
index 338338ed..0ad74155 100644
--- a/src/helpers/chem.js
+++ b/src/helpers/chem.js
@@ -5,7 +5,7 @@ max-len */
import Jcampconverter from 'jcampconverter';
import { createSelector } from 'reselect';
-import { FromManualToOffset } from './shift';
+import { shiftOffsetAtIndex } from './shift';
import Format from './format';
import { LIST_LAYOUT } from '../constants/list_layout';
import { getArea } from './integration';
@@ -48,15 +48,7 @@ const getShiftOffset = (state, _) => { // eslint-disable-line
return GetCyclicVoltaShiftOffset(cyclicvolta, curveIdx);
}
- const { shift } = state;
- const { shifts } = shift;
- const selectedShift = shifts[curveIdx];
- if (!selectedShift) {
- return 0.0;
- }
-
- const { ref, peak } = selectedShift;
- return FromManualToOffset(ref, peak);
+ return shiftOffsetAtIndex(state.shift, curveIdx);
};
const calcXYK = (xs, ys, maxY, offset) => {
diff --git a/src/helpers/compass.js b/src/helpers/compass.js
index 96f11e2d..a28d7c91 100644
--- a/src/helpers/compass.js
+++ b/src/helpers/compass.js
@@ -310,7 +310,7 @@ const ClickCompass = (event, focus) => {
} else if (isLcmsTicGraph) {
focus.clickUiTargetAct(pt, false, false, jcampIdx, false, 'lcms_tic');
} else {
- focus.clickUiTargetAct(pt, false);
+ focus.clickUiTargetAct(pt, false, 0, focus.jcampIdx);
}
};
diff --git a/src/helpers/extractPeaksEdit.js b/src/helpers/extractPeaksEdit.js
index 4930558b..8801cf6a 100644
--- a/src/helpers/extractPeaksEdit.js
+++ b/src/helpers/extractPeaksEdit.js
@@ -1,7 +1,7 @@
/* eslint-disable max-len */
import { Convert2Peak } from './chem';
import { PksEdit } from './converter';
-import { FromManualToOffset } from './shift';
+import { shiftOffsetAtIndex } from './shift';
import Format from './format';
import { calcArea } from './integration';
import {
@@ -10,21 +10,8 @@ import {
getLcmsMzPageData,
} from '../features/lc-ms/submit';
-const niOffset = (shiftSt, atIndex = 0) => {
- const { shifts } = shiftSt;
- const selectedShift = shifts[atIndex];
- if (!selectedShift) {
- return 0;
- }
- const { ref, peak } = selectedShift;
- const offset = FromManualToOffset(ref, peak);
- return offset;
-};
-
-const msOffset = () => 0;
-
const extractAutoPeaks = (feature, thresSt, shiftSt, layoutSt, atIndex = 0) => {
- const offset = (Format.isMsLayout(layoutSt) || Format.isLCMsLayout(layoutSt)) ? msOffset() : niOffset(shiftSt, atIndex);
+ const offset = (Format.isMsLayout(layoutSt) || Format.isLCMsLayout(layoutSt)) ? 0 : shiftOffsetAtIndex(shiftSt, atIndex);
const peaks = Convert2Peak(feature, thresSt.value, offset);
return peaks;
};
diff --git a/src/helpers/format.js b/src/helpers/format.js
index 049cb08a..9f010a70 100644
--- a/src/helpers/format.js
+++ b/src/helpers/format.js
@@ -35,7 +35,7 @@ const spectraDigit = (layout) => {
};
const fixDigit = (input, precision) => {
- const output = input || 0.0;
+ const output = Number(input) || 0.0;
return output.toFixed(precision);
};
@@ -111,11 +111,16 @@ const spectraOps = {
[LIST_LAYOUT.LC_MS]: { head: 'HPLC UV/VIS', tail: '' },
};
+const shiftAnchorX = (selectedShift) => {
+ if (!selectedShift) return null;
+ const x = selectedShift.ref?.value ?? selectedShift.peak?.x;
+ return x == null ? null : x;
+};
+
const rmRef = (peaks, shift, atIndex = 0) => {
- if (!shift) return peaks;
- const { shifts } = shift;
- const selectedShift = shifts[atIndex];
- const refValue = selectedShift.ref.value || selectedShift.peak.x;
+ if (!shift?.shifts) return peaks;
+ const refValue = shiftAnchorX(shift.shifts[atIndex]);
+ if (refValue == null) return peaks;
return peaks.map(
(p) => (IsSame(p.x, refValue) ? null : p),
).filter((r) => r != null);
@@ -425,37 +430,117 @@ const formatedDLSIntensity = (
return ordered.map((o) => `${o.x} nm (${o.y} %)`).join(', ');
};
+const HPLC_RT_DECIMAL = 2;
+const HPLC_VALUE_DECIMAL = 2;
+const HPLC_RT_UNIT = 'min';
+
+const formatHplcRetentionTime = (rt) => (
+ `${fixDigit(rt, HPLC_RT_DECIMAL)} ${HPLC_RT_UNIT}`
+);
+
+const formatHplcAuc = (area) => fixDigit(area, HPLC_VALUE_DECIMAL);
+
+const findHplcPeakRetentionTime = (feature, xL, xU) => {
+ if (!feature?.data?.[0]) {
+ return (xL + xU) / 2;
+ }
+ const { x, y } = feature.data[0];
+ let maxY = -Infinity;
+ let rt = (xL + xU) / 2;
+ for (let i = 0; i < x.length; i += 1) {
+ if (x[i] >= xL && x[i] <= xU && y[i] > maxY) {
+ maxY = y[i];
+ rt = x[i];
+ }
+ }
+ return rt;
+};
+
+const isSameHplcRt = (a, b) => (
+ fixDigit(a, HPLC_RT_DECIMAL) === fixDigit(b, HPLC_RT_DECIMAL)
+);
+
+const integrationApexRt = (inte, feature, peaks) => {
+ if (feature?.data?.[0]) {
+ return findHplcPeakRetentionTime(feature, inte.xL, inte.xU);
+ }
+ if (!Array.isArray(peaks)) return null;
+ const peaksInRange = peaks.filter((p) => p.x >= inte.xL && p.x <= inte.xU);
+ if (peaksInRange.length === 0) return null;
+ return peaksInRange.reduce(
+ (best, p) => (p.y > best.y ? p : best),
+ peaksInRange[0],
+ ).x;
+};
+
+const findIntegrationForPeak = (peakX, stack, peaks, feature) => {
+ if (!Array.isArray(stack)) return null;
+ const x = parseFloat(peakX);
+ return stack.find((s) => {
+ if (s.xL > x || x > s.xU) return false;
+ const apexRt = integrationApexRt(s, feature, peaks);
+ return apexRt != null && isSameHplcRt(x, apexRt);
+ }) || null;
+};
+
+const formatHplcAucPanel = (integration, feature) => {
+ if (!integration) return '';
+ const stackIntegration = integration.stack;
+ if (!Array.isArray(stackIntegration)) return '';
+
+ const entries = stackIntegration
+ .filter((inte) => inte.absoluteArea)
+ .map((inte) => ({
+ rt: findHplcPeakRetentionTime(feature, inte.xL, inte.xU),
+ area: inte.absoluteArea,
+ }));
+
+ if (entries.length === 0) return '';
+
+ const sumVal = entries.reduce((sum, e) => sum + e.area, 0);
+
+ return entries
+ .map((e) => {
+ const areaVal = formatHplcAuc(e.area);
+ const percent = fixDigit((e.area * 100) / sumVal, HPLC_VALUE_DECIMAL);
+ return `${formatHplcRetentionTime(e.rt)}, AUC=${areaVal} (${percent}%)`;
+ })
+ .join(', ');
+};
+
const formatedHplcUvVis = (
- peaks, decimal = 2, integration,
+ peaks, decimal = 2, integration, feature, isAscend = false,
) => {
let stack = [];
if (integration) {
stack = integration.stack;
}
- let ordered = {};
+ let bestByX = {};
peaks.forEach((p) => {
- const x = fixDigit(p.x, decimal);
- const better = !ordered[x] || (p.y > ordered[x]);
+ const x = Number(p.x);
+ const better = bestByX[x] === undefined || (p.y > bestByX[x]);
if (better) {
- ordered = Object.assign({}, ordered, { [x]: p.y });
+ bestByX = Object.assign({}, bestByX, { [x]: p.y });
}
});
- ordered = Object.keys(ordered)
- .map((k) => ({ x: k, y: ordered[k] }));
+ const sortFunc = isAscend
+ ? (a, b) => a.x - b.x
+ : (a, b) => b.x - a.x;
+ const ordered = Object.keys(bestByX)
+ .map((k) => ({ x: parseFloat(k), y: bestByX[k] }))
+ .sort(sortFunc);
const arrResult = [];
ordered.forEach((o) => {
- let pStr = `${o.x} (${o.y.toFixed(2)})`;
- if (stack) {
- stack.forEach((s) => {
- if (s.xL <= o.x && s.xU >= o.x) {
- pStr = `${o.x} (${o.y.toFixed(2)}, AUC=${s.absoluteArea})`;
- }
- });
- }
+ const rt = formatHplcRetentionTime(o.x);
+ const yVal = o.y.toFixed(HPLC_VALUE_DECIMAL);
+ const inte = findIntegrationForPeak(o.x, stack, peaks, feature);
+ const pStr = inte?.absoluteArea
+ ? `${rt} (${yVal}, AUC=${formatHplcAuc(inte.absoluteArea)})`
+ : `${rt} (${yVal})`;
arrResult.push(pStr);
});
@@ -488,13 +573,9 @@ const formatedXRD = (
const rmShiftFromPeaks = (peaks, shift, atIndex = 0) => {
const peaksXY = ToXY(peaks);
- const { shifts } = shift;
- const selectedShift = shifts[atIndex];
- if (!selectedShift) {
- return peaks;
- }
- // const digit = spectraDigit(layout);
- const rmShiftX = selectedShift.ref.value || selectedShift.peak.x;
+ if (!shift?.shifts) return peaks;
+ const rmShiftX = shiftAnchorX(shift.shifts[atIndex]);
+ if (rmShiftX == null) return peaks;
const result = peaksXY.map((p) => {
const srcX = parseFloat(p[0]);
const x = IsSame(srcX, rmShiftX) ? null : srcX;
@@ -508,7 +589,7 @@ const rmShiftFromPeaks = (peaks, shift, atIndex = 0) => {
const peaksBody = ({
peaks, layout, decimal, shift, isAscend,
isIntensity = false, boundary = {},
- integration, atIndex = 0, waveLength, temperature, hplcMsSt = null,
+ integration, atIndex = 0, waveLength, temperature, hplcMsSt = null, feature,
}) => {
const result = rmShiftFromPeaks(peaks, shift, atIndex);
@@ -531,7 +612,7 @@ const peaksBody = ({
return formatedUvVis(ordered, maxY, decimal, isAscend, isIntensity, boundary, false);
}
if (layout === LIST_LAYOUT.HPLC_UVVIS) {
- return formatedHplcUvVis(ordered, decimal, integration);
+ return formatedHplcUvVis(ordered, decimal, integration, feature, isAscend);
}
if (layout === LIST_LAYOUT.EMISSIONS) {
return formatedEmissions(ordered, maxY, decimal, isAscend, isIntensity, boundary, false);
@@ -556,9 +637,8 @@ const peaksBody = ({
const peaksWrapper = (layout, shift, atIndex = 0) => {
let solvTxt = '';
- const { shifts } = shift;
- const selectedShift = shifts[atIndex];
- if (selectedShift.ref.label) {
+ const selectedShift = shift?.shifts ? shift.shifts[atIndex] : shift;
+ if (selectedShift?.ref?.label) {
solvTxt = ` (${selectedShift.ref.label})`;
}
@@ -793,6 +873,8 @@ const Format = {
strNumberFixedLength,
inlineNotation,
formatedLCMS,
+ formatHplcAucPanel,
+ formatedHplcUvVis,
};
export default Format;
diff --git a/src/helpers/shift.js b/src/helpers/shift.js
index 2baaf83a..01af80f5 100644
--- a/src/helpers/shift.js
+++ b/src/helpers/shift.js
@@ -1,7 +1,31 @@
/* eslint-disable prefer-object-spread, default-param-last */
-import { LIST_SHIFT_13C } from '../constants/list_shift';
+import { LIST_SHIFT_1H } from '../constants/list_shift';
-const shiftNone = LIST_SHIFT_13C[0];
+const shiftNone = LIST_SHIFT_1H[0];
+
+const defaultEmptyShift = {
+ ref: shiftNone,
+ peak: false,
+ enable: true,
+};
+
+const listEntryAtIndex = (list, index, fallback) => (
+ Array.isArray(list) && list[index] !== undefined ? list[index] : fallback
+);
+
+const shiftEntryAtIndex = (shiftSt, atIndex = 0) => (
+ listEntryAtIndex(shiftSt?.shifts, atIndex, defaultEmptyShift)
+);
+
+const normalizeShiftForFormatting = (shift, atIndex = 0) => {
+ if (shift?.shifts) {
+ return { shift, atIndex };
+ }
+ return {
+ shift: { shifts: [shift || defaultEmptyShift] },
+ atIndex: 0,
+ };
+};
const FromManualToOffset = (ref, peak) => {
if (!peak || ref.name === shiftNone.name) return 0;
@@ -40,6 +64,19 @@ const RealPts = (pts, resX) => (
)
);
+const shiftOffsetAtIndex = (shiftSt, atIndex = 0) => {
+ const { ref, peak } = shiftEntryAtIndex(shiftSt, atIndex);
+ return FromManualToOffset(ref, peak);
+};
+
export {
- FromManualToOffset, CalcResidualX, VirtalPts, RealPts,
+ defaultEmptyShift,
+ listEntryAtIndex,
+ shiftEntryAtIndex,
+ normalizeShiftForFormatting,
+ FromManualToOffset,
+ CalcResidualX,
+ VirtalPts,
+ RealPts,
+ shiftOffsetAtIndex,
};
diff --git a/src/index.js b/src/index.js
index b789a2b4..4d7d76f0 100644
--- a/src/index.js
+++ b/src/index.js
@@ -11,6 +11,7 @@ import ReactQuill from 'react-quill';
import { SpectraEditor, FN, store } from './app';
import { getLcMsInfo } from './helpers/extractEntityLCMS';
import { snapRtToAxis } from './reducers/reducer_hplc_ms/utils';
+import { normalizeShiftForFormatting } from './helpers/shift';
import nmr1HJcamp from './__tests__/fixtures/nmr1h_jcamp';
import nmr1H2Jcamp from './__tests__/fixtures/nmr1h_2_jcamp';
import nmr13CDeptJcamp from './__tests__/fixtures/nmr13c_dept_jcamp';
@@ -70,14 +71,6 @@ const pickSelectedSpectrumFromPayload = (payload) => {
return spectraList[selectedIdx] || spectraList[0] || {};
};
-const normalizeShiftForFormatting = (shift) => {
- if (shift && Array.isArray(shift.shifts)) return shift;
- return {
- selectedIdx: 0,
- shifts: [shift || { ref: {}, peak: false, enable: true }],
- };
-};
-
const nmr1HEntity = FN.ExtractJcamp(nmr1HJcamp);
const nmr1HEntity2 = FN.ExtractJcamp(nmr1H2Jcamp);
const nmr13CEntity = FN.ExtractJcamp(nmr13CJcamp);
diff --git a/src/layer_init.js b/src/layer_init.js
index f9804c5a..fdd99c25 100644
--- a/src/layer_init.js
+++ b/src/layer_init.js
@@ -21,6 +21,12 @@ import MultiJcampsViewer from './components/multi_jcamps_viewer';
import HPLCViewer from './components/hplc_viewer';
import { setAllCurves } from './actions/curve';
import { clearHplcMsState } from './actions/hplc_ms';
+import { restoreSweepExtent } from './actions/ui';
+
+const hasActiveZoom = (sweepExtent) => {
+ if (!sweepExtent) return false;
+ return !!(sweepExtent.xExtent || sweepExtent.yExtent);
+};
const styles = () => ({
});
@@ -44,6 +50,15 @@ class LayerInit extends React.Component {
constructor(props) {
super(props);
+ const { sweepExtent, restoreSweepExtentAct } = props;
+ if (hasActiveZoom(sweepExtent)) {
+ restoreSweepExtentAct(sweepExtent);
+ } else {
+ // Clear any zoom left in the shared store by a previously opened
+ // spectrum, so it cannot block the RESETALL/layout sync on mount.
+ restoreSweepExtentAct({ xExtent: false, yExtent: false });
+ }
+
this.normChange = this.normChange.bind(this);
this.execReset = this.execReset.bind(this);
this.initReducer = this.initReducer.bind(this);
@@ -55,7 +70,7 @@ class LayerInit extends React.Component {
this.execReset();
this.initReducer();
this.updateOthers();
- this.updateMultiEntities();
+ this.updateMultiEntities(true);
}
componentDidUpdate(prevProps) {
@@ -71,7 +86,7 @@ class LayerInit extends React.Component {
}
if (prevProps.multiEntities !== multiEntities
|| prevProps.entity !== entity) {
- this.updateMultiEntities();
+ this.updateMultiEntities(false);
}
}
@@ -96,17 +111,20 @@ class LayerInit extends React.Component {
execReset() {
const {
- entity, updateMetaPeaksAct,
+ entity, updateMetaPeaksAct, updateLayoutAct,
resetInitCommonAct, resetInitMsAct, resetInitNmrAct, resetInitCommonWithIntergationAct,
- resetDetectorAct, updateDSCMetaDataAct, resetMultiplicityAct, updateLayoutAct,
+ resetDetectorAct, updateDSCMetaDataAct, resetMultiplicityAct,
} = this.props;
if (!entity || !entity.layout) return;
resetInitCommonAct();
resetDetectorAct();
const { layout, features = {} } = entity;
+ // Sync the layout deterministically on every spectrum open. Otherwise it
+ // only updates via the d3 RESETALL, which can be skipped (active zoom or
+ // same multi-comparison curve count), leaving a stale layout from the
+ // previously opened spectrum.
updateLayoutAct(layout);
if (Format.isMsLayout(layout)) {
- // const { autoPeak, editPeak } = features; // TBD
const autoPeak = features.autoPeak || features[0];
const editPeak = features.editPeak || features[0];
const baseFeat = editPeak || autoPeak;
@@ -126,7 +144,8 @@ class LayerInit extends React.Component {
} else if (Format.isDSCLayout(layout)) {
const { dscMetaData } = features;
updateDSCMetaDataAct(dscMetaData);
- } else {
+ }
+ if (!Format.isNmrLayout(layout)) {
resetMultiplicityAct();
}
}
@@ -145,7 +164,15 @@ class LayerInit extends React.Component {
}
}
- updateMultiEntities() {
+ buildSetAllCurvesPayload(entities, isInitial) {
+ const { curveIdx } = this.props;
+ if (isInitial && Number.isFinite(curveIdx)) {
+ return { entities, curveIdx };
+ }
+ return entities;
+ }
+
+ updateMultiEntities(isInitial = false) {
const { multiEntities, setAllCurvesAct, entity } = this.props;
if (!entity || !entity.layout) return;
const lcmsCurveMeta = () => {
@@ -182,23 +209,23 @@ class LayerInit extends React.Component {
const isMultiSpectra = Array.isArray(multiEntities) && multiEntities.length > 1;
if (isMultiSpectra) {
const meta = Format.isLCMsLayout(entity.layout) ? lcmsCurveMeta() : undefined;
- setAllCurvesAct(multiEntities, meta);
+ setAllCurvesAct(this.buildSetAllCurvesPayload(multiEntities, isInitial), meta);
return;
}
if (Format.isLCMsLayout(entity.layout)) {
- const payload = (Array.isArray(multiEntities) && multiEntities.length > 0)
+ const entities = (Array.isArray(multiEntities) && multiEntities.length > 0)
? multiEntities
: [entity];
- setAllCurvesAct(payload, lcmsCurveMeta());
+ setAllCurvesAct(this.buildSetAllCurvesPayload(entities, isInitial), lcmsCurveMeta());
return;
}
if (Format.isCyclicVoltaLayout(entity.layout)) {
- const payload = (Array.isArray(multiEntities) && multiEntities.length > 0)
+ const entities = (Array.isArray(multiEntities) && multiEntities.length > 0)
? multiEntities
: [entity];
- setAllCurvesAct(payload);
+ setAllCurvesAct(this.buildSetAllCurvesPayload(entities, isInitial));
return;
}
@@ -318,13 +345,23 @@ const mapDispatchToProps = (dispatch) => (
setAllCurvesAct: setAllCurves,
updateDSCMetaDataAct: updateDSCMetaData,
clearHplcMsStateAct: clearHplcMsState,
+ restoreSweepExtentAct: restoreSweepExtent,
}, dispatch)
);
+LayerInit.defaultProps = {
+ multiEntities: undefined,
+ curveIdx: undefined,
+ sweepExtent: undefined,
+};
+
LayerInit.propTypes = {
entity: PropTypes.object.isRequired,
multiEntities: PropTypes.array, // eslint-disable-line
+ curveIdx: PropTypes.number,
+ sweepExtent: PropTypes.object,
entityFileNames: PropTypes.array, // eslint-disable-line
+ restoreSweepExtentAct: PropTypes.func.isRequired,
others: PropTypes.object.isRequired,
cLabel: PropTypes.string.isRequired,
xLabel: PropTypes.string.isRequired,
diff --git a/src/reducers/reducer_curve.js b/src/reducers/reducer_curve.js
index 099c95bf..3d49e08c 100644
--- a/src/reducers/reducer_curve.js
+++ b/src/reducers/reducer_curve.js
@@ -13,8 +13,30 @@ const initialState = {
isShowAllCurve: false,
};
+const normalizeSetAllCurvesPayload = (payload) => {
+ if (Array.isArray(payload)) {
+ return { entities: payload, curveIdx: undefined };
+ }
+ if (payload && Array.isArray(payload.entities)) {
+ return { entities: payload.entities, curveIdx: payload.curveIdx };
+ }
+ return { entities: null, curveIdx: undefined };
+};
+
+const resolveCurveIdx = (entitiesLength, state, explicitIdx) => {
+ if (Number.isFinite(explicitIdx)) {
+ const maxIdx = Math.max(0, entitiesLength - 1);
+ return Math.min(Math.max(0, explicitIdx), maxIdx);
+ }
+ if (state.curveIdx >= 0 && state.curveIdx < entitiesLength) {
+ return state.curveIdx;
+ }
+ return 0;
+};
+
const setAllCurves = (state, action) => {
- const { payload } = action;
+ const { entities: payloadEntities, curveIdx: explicitIdx } = normalizeSetAllCurvesPayload(action.payload);
+ const payload = payloadEntities ?? action.payload;
if (!payload) return { ...state, curveIdx: 0, listCurves: [] };
const isLcmsGroup = isLcMsGroup(payload);
@@ -55,12 +77,11 @@ const setAllCurves = (state, action) => {
};
});
- const maxIdx = entities.length - 1;
- const safeCurveIdx = Math.min(state.curveIdx || 0, maxIdx);
+ const curveIdx = resolveCurveIdx(entities.length, state, explicitIdx);
return {
...state,
- curveIdx: safeCurveIdx,
+ curveIdx,
listCurves: entities,
};
};
diff --git a/src/reducers/reducer_edit_peak.js b/src/reducers/reducer_edit_peak.js
index 45079f7c..d3fbd43a 100644
--- a/src/reducers/reducer_edit_peak.js
+++ b/src/reducers/reducer_edit_peak.js
@@ -1,6 +1,6 @@
/* eslint-disable prefer-object-spread, default-param-last */
import undoable from 'redux-undo';
-import { EDITPEAK, MANAGER } from '../constants/action_type';
+import { EDITPEAK, MANAGER, CURVE } from '../constants/action_type';
import { undoRedoConfig, undoRedoActions } from './undo_redo_config';
import { almostEqual } from '../helpers/calc';
@@ -170,6 +170,8 @@ const editPeakReducer = (state = initialState, action) => {
return processShift(state, action);
case EDITPEAK.CLEAR_ALL:
return clearAllPeaks(state, action);
+ case CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, { selectedIdx: action.payload });
case MANAGER.RESETALL:
return {
selectedIdx: 0,
diff --git a/src/reducers/reducer_integration.js b/src/reducers/reducer_integration.js
index 22fd0667..992e2b30 100644
--- a/src/reducers/reducer_integration.js
+++ b/src/reducers/reducer_integration.js
@@ -1,7 +1,7 @@
/* eslint-disable prefer-object-spread, default-param-last */
import undoable from 'redux-undo';
import {
- UI, INTEGRATION, EDITPEAK, MANAGER,
+ UI, INTEGRATION, EDITPEAK, MANAGER, CURVE,
} from '../constants/action_type';
import {
generateVisualSplitGroupId,
@@ -455,15 +455,18 @@ const setFkr = (state, action) => {
};
const setShift = (state, action) => {
- const { selectedIdx, integrations } = state;
- const selectedIntegration = integrations[selectedIdx];
-
- const shift = action.payload.prevOffset;
+ const { integrations } = state;
+ const { prevOffset, curveIdx } = action.payload;
+ const targetIdx = Number.isFinite(curveIdx) ? curveIdx : state.selectedIdx;
+ let selectedIntegration = integrations[targetIdx];
+ if (selectedIntegration === false || selectedIntegration === undefined) {
+ selectedIntegration = defaultEmptyIntegration;
+ }
- const newIntegration = Object.assign({}, selectedIntegration, { shift });
+ const newIntegration = Object.assign({}, selectedIntegration, { shift: prevOffset });
const newArrIntegration = [...integrations];
- newArrIntegration[selectedIdx] = newIntegration;
- return Object.assign({}, state, { integrations: newArrIntegration });
+ newArrIntegration[targetIdx] = newIntegration;
+ return Object.assign({}, state, { integrations: newArrIntegration, selectedIdx: targetIdx });
};
const resetAll = (state, action) => {
@@ -504,6 +507,8 @@ const integrationReducer = (state = initialState, action) => {
return clearAll(state, action);
case EDITPEAK.SHIFT:
return setShift(state, action);
+ case CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, { selectedIdx: action.payload });
case MANAGER.RESETALL:
return state;
default:
diff --git a/src/reducers/reducer_multiplicity.js b/src/reducers/reducer_multiplicity.js
index d8195147..f531f809 100644
--- a/src/reducers/reducer_multiplicity.js
+++ b/src/reducers/reducer_multiplicity.js
@@ -1,7 +1,7 @@
/* eslint-disable prefer-object-spread, default-param-last */
import undoable from 'redux-undo';
import {
- UI, EDITPEAK, INTEGRATION, MULTIPLICITY, MANAGER,
+ UI, EDITPEAK, INTEGRATION, MULTIPLICITY, MANAGER, CURVE,
} from '../constants/action_type';
import { undoRedoConfig, undoRedoActions } from './undo_redo_config';
@@ -26,15 +26,19 @@ const defaultEmptyMultiplicity = {
};
const setShift = (state, action) => {
- const shift = action.payload.prevOffset;
+ const { prevOffset, curveIdx } = action.payload;
+ const targetIdx = Number.isFinite(curveIdx) ? curveIdx : state.selectedIdx;
- const { selectedIdx, multiplicities } = state;
- const selectedMulti = multiplicities[selectedIdx];
+ const { multiplicities } = state;
+ let selectedMulti = multiplicities[targetIdx];
+ if (selectedMulti === false || selectedMulti === undefined) {
+ selectedMulti = defaultEmptyMultiplicity;
+ }
- const newSelectedMulti = Object.assign({}, selectedMulti, { shift });
+ const newSelectedMulti = Object.assign({}, selectedMulti, { shift: prevOffset });
const newMultiplicities = [...multiplicities];
- newMultiplicities[selectedIdx] = newSelectedMulti;
- return Object.assign({}, state, { multiplicities: newMultiplicities });
+ newMultiplicities[targetIdx] = newSelectedMulti;
+ return Object.assign({}, state, { multiplicities: newMultiplicities, selectedIdx: targetIdx });
};
const rmFromStack = (state, action) => {
@@ -127,6 +131,8 @@ const multiplicityReducer = (state = initialState, action) => {
switch (action.type) {
case EDITPEAK.SHIFT:
return setShift(state, action);
+ case CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, { selectedIdx: action.payload });
case INTEGRATION.RM_ONE:
return rmFromStack(state, action);
case UI.SWEEP.SELECT_MULTIPLICITY_RDC:
diff --git a/src/reducers/reducer_shift.js b/src/reducers/reducer_shift.js
index ad1446c5..57924a68 100644
--- a/src/reducers/reducer_shift.js
+++ b/src/reducers/reducer_shift.js
@@ -1,9 +1,9 @@
/* eslint-disable prefer-object-spread, default-param-last */
import {
- SHIFT, EDITPEAK, MANAGER, LAYOUT,
+ SHIFT, EDITPEAK, MANAGER, LAYOUT, CURVE,
} from '../constants/action_type';
import { getListShift, LIST_SHIFT_1H } from '../constants/list_shift';
-import { CalcResidualX, RealPts } from '../helpers/shift';
+import { CalcResidualX, RealPts, defaultEmptyShift } from '../helpers/shift';
const shiftNone = LIST_SHIFT_1H[0];
const normalizeShiftName = (input) => (
@@ -31,12 +31,6 @@ const initialState = {
],
};
-const defaultEmptyShift = {
- ref: shiftNone,
- peak: false,
- enable: true,
-};
-
const resetRef = (payload) => {
const { shift, layout } = payload;
if (!shift || !shift.solventName || !shift.solventValue) return shiftNone;
@@ -68,7 +62,7 @@ const resetShift = (state, action) => {
const { curvesInfo } = payload;
const { isMultiCurve, curveIdx, numberOfCurve } = curvesInfo;
- const { shifts } = state;
+ const shifts = [...state.shifts];
let selectedShift = shifts[curveIdx];
if (selectedShift === false || selectedShift === undefined) {
selectedShift = defaultEmptyShift;
@@ -238,7 +232,9 @@ const shiftReducer = (state = initialState, action) => {
case LAYOUT.UPDATE:
return updateShift(initialState, action);
case MANAGER.RESETSHIFT: // case MANAGER.RESETALL:
- return resetShift(initialState, action);
+ return resetShift(state, action);
+ case CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, { selectedIdx: action.payload });
default:
return state;
}
diff --git a/src/reducers/reducer_threshold.js b/src/reducers/reducer_threshold.js
index 9755c67d..b62b6d72 100644
--- a/src/reducers/reducer_threshold.js
+++ b/src/reducers/reducer_threshold.js
@@ -13,12 +13,12 @@ const initialState = {
],
};
-// const defaultThresHold = {
-// isEdit: true,
-// value: false,
-// upper: false,
-// lower: false,
-// };
+const defaultThresHold = {
+ isEdit: true,
+ value: false,
+ upper: false,
+ lower: false,
+};
const setThresHoldValue = (state, action) => {
const { payload } = action;
@@ -77,19 +77,34 @@ const setThresHoldLower = (state, action) => {
return Object.assign({}, state, { list: newListThres });
};
-const setThresHoldIsEdit = (state) => {
+const setThresHoldIsEdit = (state, action) => {
+ const { payload } = action;
const { list, selectedIdx } = state;
- const selectedThres = list[selectedIdx];
+ const curveIdx = payload && payload.curveIdx !== undefined ? payload.curveIdx : selectedIdx;
+ const selectedThres = list[curveIdx] || defaultThresHold;
const { isEdit } = selectedThres;
const newSelectedThres = Object.assign({}, selectedThres, { isEdit: !isEdit });
const newListThres = [...list];
- newListThres[selectedIdx] = newSelectedThres;
- return Object.assign({}, state, { list: newListThres });
+ newListThres[curveIdx] = newSelectedThres;
+ return Object.assign({}, state, { list: newListThres, selectedIdx: curveIdx });
};
const resetAll = (state, action) => {
const { payload } = action;
const { list } = state;
+ if (payload && payload.curveIdx !== undefined) {
+ const { curveIdx } = payload;
+ const selectedThres = list[curveIdx] || defaultThresHold;
+ const newSelectedThres = Object.assign(
+ {},
+ selectedThres,
+ { value: payload.thresRef },
+ );
+ const newListThres = [...list];
+ newListThres[curveIdx] = newSelectedThres;
+ return Object.assign({}, state, { selectedIdx: curveIdx, list: newListThres });
+ }
+
const newList = list.map((item) => (
{
isEdit: item.isEdit,
@@ -149,6 +164,8 @@ const thresholdReducer = (state = initialState, action) => {
switch (action.type) {
case CURVE.SET_ALL_CURVES:
return setListThreshold(state, action);
+ case CURVE.SELECT_WORKING_CURVE:
+ return Object.assign({}, state, { selectedIdx: action.payload });
case THRESHOLD.UPDATE_VALUE:
return setThresHoldValue(state, action);
case THRESHOLD.UPDATE_UPPER_VALUE:
@@ -158,7 +175,7 @@ const thresholdReducer = (state = initialState, action) => {
case THRESHOLD.RESET_VALUE:
return setThresHoldValue(state, action);
case THRESHOLD.TOGGLE_ISEDIT:
- return setThresHoldIsEdit(state);
+ return setThresHoldIsEdit(state, action);
case MANAGER.RESET_INIT_COMMON:
return resetInitCommon(state);
case MANAGER.RESETALL:
diff --git a/src/sagas/saga_manager.js b/src/sagas/saga_manager.js
index 9ac6e748..17ab5aab 100644
--- a/src/sagas/saga_manager.js
+++ b/src/sagas/saga_manager.js
@@ -8,6 +8,14 @@ const getLayout = (state) => state.layout;
const getCurveSt = (state) => state.curve;
const getIntegrationSt = (state) => state.integration.present;
+const defaultEmptyIntegration = {
+ stack: [],
+ refArea: 1,
+ refFactor: 1,
+ shift: 0,
+ edited: false,
+};
+
function* resetShift(action) {
const curveSt = yield select(getCurveSt);
const layout = yield select(getLayout);
@@ -16,7 +24,7 @@ function* resetShift(action) {
const { curveIdx, listCurves } = curveSt;
- const numberOfCurve = listCurves.length;
+ const numberOfCurve = Array.isArray(listCurves) ? listCurves.length : 0;
yield put({
type: MANAGER.RESETSHIFT,
@@ -41,18 +49,17 @@ function* resetInitNmr(action) {
const { curveIdx } = curveSt;
const { integration, simulation } = action.payload;
- const { integrations } = integationSt;
- const newArrIntegration = [...integrations];
- newArrIntegration[curveIdx] = integration;
+ // Always reset: keeping the previous spectrum's integrations would
+ // display stale data when the new entity has none saved.
+ const newArrIntegration = new Array(curveIdx + 1).fill(defaultEmptyIntegration);
+ newArrIntegration[curveIdx] = integration || defaultEmptyIntegration;
const payload = Object.assign({}, integationSt, { integrations: newArrIntegration, selectedIdx: curveIdx }); // eslint-disable-line
- if (integration) {
- yield put({
- type: INTEGRATION.RESET_ALL_RDC,
- payload,
- });
- }
+ yield put({
+ type: INTEGRATION.RESET_ALL_RDC,
+ payload,
+ });
if (simulation) {
yield put({
type: SIMULATION.RESET_ALL_RDC,
@@ -68,18 +75,15 @@ function* resetInitCommonWithIntergation(action) {
const { integration } = action.payload;
- const { integrations } = integationSt;
- const newArrIntegration = [...integrations];
- newArrIntegration[curveIdx] = integration;
+ const newArrIntegration = new Array(curveIdx + 1).fill(defaultEmptyIntegration);
+ newArrIntegration[curveIdx] = integration || defaultEmptyIntegration;
const payload = Object.assign({}, integationSt, { integrations: newArrIntegration, selectedIdx: curveIdx }); // eslint-disable-line
- if (integration) {
- yield put({
- type: INTEGRATION.RESET_ALL_RDC,
- payload,
- });
- }
+ yield put({
+ type: INTEGRATION.RESET_ALL_RDC,
+ payload,
+ });
}
const managerSagas = [
diff --git a/src/sagas/saga_multi_entities.js b/src/sagas/saga_multi_entities.js
index 3a72db3a..e2d3a7f6 100644
--- a/src/sagas/saga_multi_entities.js
+++ b/src/sagas/saga_multi_entities.js
@@ -2,7 +2,7 @@
import { put, takeEvery, select } from 'redux-saga/effects';
import {
- CURVE, CYCLIC_VOLTA_METRY, INTEGRATION, SIMULATION, MULTIPLICITY,
+ CURVE, CYCLIC_VOLTA_METRY, INTEGRATION, SIMULATION, MULTIPLICITY, MANAGER,
} from '../constants/action_type';
import { LIST_LAYOUT } from '../constants/list_layout';
@@ -121,6 +121,34 @@ function* setCyclicVoltametryRef(action) { // eslint-disable-line
}));
}
+function* setInitShifts() {
+ const curveSt = yield select(getCurveSt);
+ const { listCurves } = curveSt;
+ if (!listCurves || listCurves.length <= 1) {
+ return;
+ }
+
+ const layoutSt = yield select(getLayoutSt);
+ const numberOfCurve = listCurves.length;
+ for (let index = 0; index < listCurves.length; index += 1) {
+ const { feature } = listCurves[index];
+ if (feature) {
+ yield put({
+ type: MANAGER.RESETSHIFT,
+ payload: {
+ ...feature,
+ layout: layoutSt,
+ curvesInfo: {
+ isMultiCurve: true,
+ curveIdx: index,
+ numberOfCurve,
+ },
+ },
+ });
+ }
+ }
+}
+
function* setInitIntegrations(action) { // eslint-disable-line
const curveSt = yield select(getCurveSt);
const { listCurves } = curveSt;
@@ -173,6 +201,7 @@ function* setInitIntegrations(action) { // eslint-disable-line
const multiEntitiesSagas = [
takeEvery(CURVE.SET_ALL_CURVES, setCyclicVoltametry),
+ takeEvery(CURVE.SET_ALL_CURVES, setInitShifts),
takeEvery(CURVE.SET_ALL_CURVES, setInitIntegrations),
takeEvery(CYCLIC_VOLTA_METRY.SET_FACTOR, setCyclicVoltametryRef),
];
diff --git a/src/sagas/saga_multiplicity.js b/src/sagas/saga_multiplicity.js
index d70a0446..b32bdcdf 100644
--- a/src/sagas/saga_multiplicity.js
+++ b/src/sagas/saga_multiplicity.js
@@ -9,6 +9,13 @@ const getCurveSt = (state) => state.curve;
const getMultiplicitySt = (state) => state.multiplicity.present;
+const defaultEmptyMultiplicity = {
+ stack: [],
+ shift: 0,
+ smExtext: false,
+ edited: false,
+};
+
function* selectMpy(action) {
const metaSt = yield select(getMetaSt);
const mpySt = yield select(getMultiplicitySt);
@@ -201,26 +208,16 @@ function* resetInitNmr(action) {
const mpySt = yield select(getMultiplicitySt);
const { curveIdx } = curveSt;
- const { multiplicities } = mpySt;
- const newMultiplicities = [...multiplicities];
- newMultiplicities[curveIdx] = multiplicity;
+ // Always reset: keeping the previous spectrum's multiplicities would
+ // display stale data when the new entity has none saved.
+ const newMultiplicities = new Array(curveIdx + 1).fill(defaultEmptyMultiplicity);
+ newMultiplicities[curveIdx] = multiplicity || defaultEmptyMultiplicity;
const payload = Object.assign({}, mpySt, { multiplicities: newMultiplicities, selectedIdx: curveIdx }); // eslint-disable-line
- if (multiplicity) {
- yield put({
- type: MULTIPLICITY.RESET_ALL_RDC,
- payload,
- });
- }
- // const metaSt = yield select(getMetaSt);
- // const mpySt = yield select(getMultiplicitySt);
-
- // if (!multiplicity) {
- // yield put({
- // type: MULTIPLICITY.RESET_ALL_RDC,
- // payload: mpySt,
- // });
- // }
+ yield put({
+ type: MULTIPLICITY.RESET_ALL_RDC,
+ payload,
+ });
// const { stack } = multiplicity;
// const newStack = stack.map((k) => {
diff --git a/src/sagas/saga_ui.js b/src/sagas/saga_ui.js
index 8458dc86..25f0976c 100644
--- a/src/sagas/saga_ui.js
+++ b/src/sagas/saga_ui.js
@@ -168,12 +168,13 @@ export const shouldDisplayLcmsSubViewerAt = ({
function* clickUiTarget(action) {
const {
- payload, onPeak, voltammetryPeakIdx, onPecker, sourceHint,
+ payload, onPeak, voltammetryPeakIdx, onPecker, sourceHint, jcampIdx,
} = action;
const uiSweepType = yield select(getUiSweepType);
const curveState = yield select(getCurveState);
const { curveIdx } = curveState;
+ const targetCurveIdx = Number.isFinite(jcampIdx) ? jcampIdx : curveIdx;
const hplcMsState = yield select(getHplcMsState);
const { uvvis } = hplcMsState;
@@ -208,7 +209,7 @@ function* clickUiTarget(action) {
} else {
yield put({
type: EDITPEAK.ADD_POSITIVE,
- payload: { dataToAdd: payload, curveIdx },
+ payload: { dataToAdd: payload, curveIdx: targetCurveIdx },
});
}
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.PEAK_DELETE && onPeak) {
@@ -217,13 +218,13 @@ function* clickUiTarget(action) {
} else {
yield put({
type: EDITPEAK.ADD_NEGATIVE,
- payload: { dataToAdd: payload, curveIdx },
+ payload: { dataToAdd: payload, curveIdx: targetCurveIdx },
});
}
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.ANCHOR_SHIFT && onPeak) {
yield put({
type: SHIFT.SET_PEAK,
- payload: { dataToSet: payload, curveIdx },
+ payload: { dataToSet: payload, curveIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.INTEGRATION_RM && onPeak) {
if (uvvis.selectedWaveLength && isLcmsLayout) {
@@ -231,30 +232,30 @@ function* clickUiTarget(action) {
} else {
yield put({
type: INTEGRATION.RM_ONE,
- payload: { dataToRemove: payload, curveIdx },
+ payload: { dataToRemove: payload, curveIdx: targetCurveIdx },
});
}
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.MULTIPLICITY_ONE_RM && onPeak) {
yield put({
type: INTEGRATION.RM_ONE,
- payload: { dataToRemove: payload, curveIdx },
+ payload: { dataToRemove: payload, curveIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.INTEGRATION_SET_REF && onPeak) {
yield put({
type: INTEGRATION.SET_REF,
- payload: { refData: payload, curveIdx },
+ payload: { refData: payload, curveIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.MULTIPLICITY_ONE_CLICK && onPeak) {
const { xExtent, xL, xU } = payload;
if (xExtent) {
yield put({
type: MULTIPLICITY.ONE_CLICK_BY_UI,
- payload: { payloadData: xExtent, curveIdx },
+ payload: { payloadData: xExtent, curveIdx: targetCurveIdx },
});
} else if (xL && xU) {
yield put({
type: MULTIPLICITY.ONE_CLICK_BY_UI,
- payload: { payloadData: { xL, xU }, curveIdx },
+ payload: { payloadData: { xL, xU }, curveIdx: targetCurveIdx },
});
}
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.MULTIPLICITY_PEAK_ADD) {
@@ -270,37 +271,37 @@ function* clickUiTarget(action) {
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_ADD_MAX_PEAK && !onPeak) {
yield put({
type: CYCLIC_VOLTA_METRY.ADD_MAX_PEAK,
- payload: { peak: payload, index: voltammetryPeakIdx, jcampIdx: curveIdx },
+ payload: { peak: payload, index: voltammetryPeakIdx, jcampIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_RM_MAX_PEAK && onPeak) {
yield put({
type: CYCLIC_VOLTA_METRY.REMOVE_MAX_PEAK,
- payload: { index: voltammetryPeakIdx, jcampIdx: curveIdx },
+ payload: { index: voltammetryPeakIdx, jcampIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_ADD_MIN_PEAK && !onPeak) {
yield put({
type: CYCLIC_VOLTA_METRY.ADD_MIN_PEAK,
- payload: { peak: payload, index: voltammetryPeakIdx, jcampIdx: curveIdx },
+ payload: { peak: payload, index: voltammetryPeakIdx, jcampIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_RM_MIN_PEAK && onPeak) {
yield put({
type: CYCLIC_VOLTA_METRY.REMOVE_MIN_PEAK,
- payload: { index: voltammetryPeakIdx, jcampIdx: curveIdx },
+ payload: { index: voltammetryPeakIdx, jcampIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_ADD_PECKER && !onPecker) {
yield put({
type: CYCLIC_VOLTA_METRY.ADD_PECKER,
- payload: { peak: payload, index: voltammetryPeakIdx, jcampIdx: curveIdx },
+ payload: { peak: payload, index: voltammetryPeakIdx, jcampIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_RM_PECKER && onPecker) {
yield put({
type: CYCLIC_VOLTA_METRY.REMOVE_PECKER,
- payload: { index: voltammetryPeakIdx, jcampIdx: curveIdx },
+ payload: { index: voltammetryPeakIdx, jcampIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.CYCLIC_VOLTA_SET_REF && onPeak) {
yield put({
type: CYCLIC_VOLTA_METRY.SET_REF,
- payload: { index: voltammetryPeakIdx, jcampIdx: curveIdx },
+ payload: { index: voltammetryPeakIdx, jcampIdx: targetCurveIdx },
});
} else if (uiSweepType === LIST_UI_SWEEP_TYPE.PEAK_GROUP_SELECT) {
yield put({