Skip to content

Commit

Permalink
feat: Add new tool to draw exclusion zones
Browse files Browse the repository at this point in the history
  • Loading branch information
hamed-musallam committed Apr 22, 2021
1 parent 8ba8fc9 commit 1d48ebd
Show file tree
Hide file tree
Showing 17 changed files with 185 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/component/1d/Chart1D.jsx
@@ -1,4 +1,5 @@
import BaseLineZones from './BaseLineZones';
import ExclusionZones from './ExclusionZones';
import IntegralsSeries from './IntegralsSeries';
import LinesSeries from './LinesSeries';
import PeaksNotations from './PeaksNotations';
Expand Down Expand Up @@ -31,6 +32,7 @@ function Chart1D({ mode, width, height, margin, displayerKey }) {
<Ranges />
<MultiAnalysisRanges />
<BaseLineZones />
<ExclusionZones />

<g className="container" style={{ pointerEvents: 'none' }}>
<XAxis showGrid mode={mode} />
Expand Down
55 changes: 55 additions & 0 deletions src/component/1d/ExclusionZones.jsx
@@ -0,0 +1,55 @@
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';

import { useScale } from '../context/ScaleContext';
import { TYPES, useHighlight } from '../highlight';
import ExclusionZonesWrapper from '../hoc/ExclusionZonesWrapper';

const styles = css`
pointer-events: bounding-box;
user-select: 'none';
-webkit-user-select: none; /* Chrome all / Safari all */
-moz-user-select: none; /* Firefox all */
.zone-area {
height: 100%;
fill: #dddddd;
cursor: pointer;
}
.zone-area.active {
fill: #ff6f0057;
}
`;

const ExclusionZone = ({ zone }) => {
const { scaleX } = useScale();
const highlight = useHighlight([zone.id], TYPES.EXCLUSION_ZONE);
return (
<g
key={zone.id}
transform={`translate(${scaleX()(zone.to)},0)`}
css={styles}
{...highlight.onHover}
>
<rect
x="0"
width={`${scaleX()(zone.from) - scaleX()(zone.to)}`}
className={`zone-area ${highlight.isActive && 'active'}`}
/>
</g>
);
};

function ExclusionZones({ exclusionZones }) {
if (!exclusionZones) return null;

return (
<g className="exclusionZones">
{exclusionZones.map((zone) => (
<ExclusionZone key={zone.id} zone={zone} />
))}
</g>
);
}

export default ExclusionZonesWrapper(ExclusionZones);
21 changes: 15 additions & 6 deletions src/component/1d/Viewer1D.jsx
Expand Up @@ -29,6 +29,7 @@ import {
SET_DIMENSIONS,
ADD_RANGE,
ANALYZE_SPECTRA,
ADD_EXCLUSION_ZONE,
} from '../reducer/types/Types';
import BrushXY, { BRUSH_TYPE } from '../tool/BrushXY';
import CrossLinePointer from '../tool/CrossLinePointer';
Expand Down Expand Up @@ -161,20 +162,28 @@ function Viewer1D({ emptyText = undefined }) {
...brushData,
});
break;
default:
propagateEvent(brushData);

break;
}
} else {
switch (selectedTool) {
case options.baseLineCorrection.id:
dispatch({
type: ADD_BASE_LINE_ZONE,
zone: { from: brushData.startX, to: brushData.endX },
});
break;

case options.exclusionZones.id:
dispatch({
type: ADD_EXCLUSION_ZONE,
payload: { from: brushData.startX, to: brushData.endX },
});
break;

default:
propagateEvent(brushData);

break;
}
} else {
switch (selectedTool) {
default:
if (selectedTool != null) {
dispatch({ type: BRUSH_END, ...brushData });
Expand Down
10 changes: 10 additions & 0 deletions src/component/EventsTrackers/KeysListenerTracker.js
Expand Up @@ -17,6 +17,7 @@ import {
DELETE_PEAK_NOTATION,
DELETE_RANGE,
DELETE_2D_ZONE,
DELETE_EXCLUSION_ZONE,
} from '../reducer/types/Types';
import { options } from '../toolbar/ToolTypes';

Expand Down Expand Up @@ -88,6 +89,15 @@ function KeysListenerTracker() {
});
break;
}
case TYPES.EXCLUSION_ZONE: {
dispatch({
type: DELETE_EXCLUSION_ZONE,
payload: {
id: data.activeKey,
},
});
break;
}
default:
break;
}
Expand Down
2 changes: 2 additions & 0 deletions src/component/NMRium.tsx
Expand Up @@ -442,6 +442,7 @@ NMRium.propTypes = {
hidePhaseCorrectionTool: PropTypes.bool,
hideBaseLineCorrectionTool: PropTypes.bool,
hideFFTTool: PropTypes.bool,
hideExclusionZonesTool: PropTypes.bool,
}),
}),
};
Expand Down Expand Up @@ -484,6 +485,7 @@ NMRium.defaultProps = {
hideBaseLineCorrectionTool: false,
hideFFTTool: false,
hideMultipleSpectraAnalysisTool: false,
hideExclusionZonesTool: false,
},
},
};
Expand Down
1 change: 1 addition & 0 deletions src/component/highlight/index.js
Expand Up @@ -12,6 +12,7 @@ export const TYPES = {
INTEGRAL: 'INTEGRAL',
RANGE: 'RANGE',
ZONE: 'ZONE',
EXCLUSION_ZONE: 'EXCLUSION_ZONE',
};

const highlightContext = createContext();
Expand Down
21 changes: 21 additions & 0 deletions src/component/hoc/ExclusionZonesWrapper.js
@@ -0,0 +1,21 @@
import { useChartData } from '../context/ChartContext';

function ExclusionZonesWrapper(WrappedComponent) {
const Wrapper = (props) => {
const { exclusionZones, activeTab } = useChartData();

return (
<WrappedComponent
{...props}
exclusionZones={
exclusionZones[activeTab] ? exclusionZones[activeTab] : null
}
/>
);
};

return (props) => {
return <Wrapper {...props} />;
};
}
export default ExclusionZonesWrapper;
11 changes: 9 additions & 2 deletions src/component/reducer/Reducer.ts
Expand Up @@ -92,6 +92,7 @@ export const initialState = {
displayerKey: '',
ZoomHistory: {},
overDisplayer: false,
exclusionZones: {},
};

export interface State {
Expand Down Expand Up @@ -139,9 +140,10 @@ export interface State {
spectraAnalysis: any;
displayerKey: any;
correlations: Types.CorrelationData;
actionType: null;
ZoomHistory: any;
overDisplayer: boolean;
exclusionZones: {
[key: string]: Array<{ id: string; from: number; to: number }>;
};
}

export function dispatchMiddleware(dispatch) {
Expand Down Expand Up @@ -389,6 +391,11 @@ function innerSpectrumReducer(draft, action) {
return ToolsActions.handleAddBaseLineZone(draft, action.zone);
case types.DELETE_BASE_LINE_ZONE:
return ToolsActions.handleDeleteBaseLineZone(draft, action.id);
case types.ADD_EXCLUSION_ZONE:
return ToolsActions.handleAddExclusionZone(draft, action);
case types.DELETE_EXCLUSION_ZONE:
return ToolsActions.handleDeleteExclusionZone(draft, action);

case types.APPLY_BASE_LINE_CORRECTION_FILTER:
return FiltersActions.handleBaseLineCorrectionFilter(draft, action);
case types.SET_KEY_PREFERENCES:
Expand Down
5 changes: 4 additions & 1 deletion src/component/reducer/actions/LoadActions.ts
Expand Up @@ -26,24 +26,27 @@ function setData(
molecules: Molecules;
preferences: NMRiumPreferences;
correlations: Types.CorrelationData;
exclusionZones: any;
},
) {
const {
spectra,
molecules,
preferences,
correlations,
// multipleAnalysis,
exclusionZones = {},
} = data || {
spectra: [],
molecules: [],
preferences: {},
correlations: {},
multipleAnalysis: {},
exclusionZones: {},
};
draft.data = spectra;
draft.molecules = MoleculeManager.fromJSON(molecules);
draft.preferences = preferences;
draft.exclusionZones = exclusionZones;

if (!correlations || Object.keys(correlations).length === 0) {
draft.correlations = Build.init({
Expand Down
35 changes: 35 additions & 0 deletions src/component/reducer/actions/ToolsActions.ts
Expand Up @@ -509,6 +509,39 @@ function resetSpectraScale(draft: Draft<State>) {
}
}

function handleAddExclusionZone(draft: Draft<State>, action) {
const { from, to } = action.payload;
const scaleX = getXScale(draft);

const start = scaleX.invert(from);
const end = scaleX.invert(to);

let zone: any = [];
if (start > end) {
zone = [end, start];
} else {
zone = [start, end];
}
const newExclusionZone = {
id: generateID(),
from: zone[0],
to: zone[1],
};
if (draft.exclusionZones[draft.activeTab]) {
draft.exclusionZones[draft.activeTab].push(newExclusionZone);
} else {
draft.exclusionZones[draft.activeTab] = [newExclusionZone];
}
}

function handleDeleteExclusionZone(draft: Draft<State>, action) {
const id = action.payload.id;
const index = draft.exclusionZones[draft.activeTab].findIndex(
(zone) => zone.id === id,
);
draft.exclusionZones[draft.activeTab].splice(index, 1);
}

export {
resetSelectedTool,
setSelectedTool,
Expand All @@ -528,4 +561,6 @@ export {
setTab,
setSpectraSameTopHandler,
resetSpectraScale,
handleAddExclusionZone,
handleDeleteExclusionZone,
};
2 changes: 2 additions & 0 deletions src/component/reducer/types/Types.js
Expand Up @@ -107,3 +107,5 @@ export const SET_SPECTRA_SAME_TOP = 'SET_SPECTRA_SAME_TOP';
export const RESET_SPECTRA_SCALE = 'RESET_SPECTRA_SCALE';
export const SET_MOUSE_OVER_DISPLAYER = 'SET_MOUSE_OVER_DISPLAYER';
export const APPLY_FROM_TO_FILTER = 'APPLY_FROM_TO_FILTER';
export const ADD_EXCLUSION_ZONE = 'ADD_EXCLUSION_ZONE';
export const DELETE_EXCLUSION_ZONE = 'DELETE_EXCLUSION_ZONE';
1 change: 1 addition & 0 deletions src/component/tool/BrushX.jsx
Expand Up @@ -21,6 +21,7 @@ const allowTools = [
options.phaseCorrection.id,
options.baseLineCorrection.id,
options.rangesPicking.id,
options.exclusionZones.id,
];

export default function BrushX() {
Expand Down
1 change: 1 addition & 0 deletions src/component/tool/BrushXY.jsx
Expand Up @@ -26,6 +26,7 @@ const allowTools = [
options.slicingTool.id,
options.editRange.id,
options.multipleSpectraAnalysis.id,
options.exclusionZones.id,
];

export const BRUSH_TYPE = {
Expand Down
1 change: 1 addition & 0 deletions src/component/tool/CrossLinePointer.jsx
Expand Up @@ -25,6 +25,7 @@ const allowTools = [
options.rangesPicking.id,
options.editRange.id,
options.multipleSpectraAnalysis.id,
options.exclusionZones.id,
];

function CrossLinePointer() {
Expand Down
17 changes: 17 additions & 0 deletions src/component/toolbar/FunctionToolBar.jsx
Expand Up @@ -314,6 +314,23 @@ function FunctionToolBar({
</ToolTip>
</ToggleButton>
)}

{displayerMode === DISPLAYER_MODE.DM_1D &&
isButtonVisible('hideExclusionZonesTool') && (
<ToggleButton
key={options.exclusionZones.id}
value={options.exclusionZones.id}
className="cheminfo"
>
<ToolTip
title={options.exclusionZones.label}
popupPlacement="right"
offset={{ x: 10, y: 0 }}
>
<SvgNmrMultipleAnalysis />
</ToolTip>
</ToggleButton>
)}
</ToggleButtonGroup>

{displayerMode === DISPLAYER_MODE.DM_1D &&
Expand Down
6 changes: 6 additions & 0 deletions src/component/toolbar/ToolTypes.js
Expand Up @@ -87,4 +87,10 @@ export const options = {
hasOptionPanel: false,
isFilter: false,
},
exclusionZones: {
id: 'exclusionZones',
label: 'Exclusion Zones',
hasOptionPanel: false,
isFilter: false,
},
};
3 changes: 3 additions & 0 deletions src/data/SpectraManager.js
Expand Up @@ -209,12 +209,14 @@ export function toJSON(state) {
preferences,
correlations,
multipleAnalysis,
exclusionZones,
} = state || {
data: [],
molecules: [],
preferences: {},
correlations: {},
multipleAnalysis: {},
exclusionZones: {},
};
const spectra = data.map((ob) => {
return ob.info.dimension === 1 ? Datum1D.toJSON(ob) : Datum2D.toJSON(ob);
Expand All @@ -226,5 +228,6 @@ export function toJSON(state) {
preferences,
correlations,
multipleAnalysis,
exclusionZones,
};
}

0 comments on commit 1d48ebd

Please sign in to comment.