Skip to content

Commit

Permalink
[HCS images] Ability to lock ranges of the channels (#2528)
Browse files Browse the repository at this point in the history
  • Loading branch information
rodichenko committed Mar 3, 2022
1 parent f263901 commit ac0dc51
Show file tree
Hide file tree
Showing 15 changed files with 174 additions and 25 deletions.
2 changes: 0 additions & 2 deletions client/public/hcs-image-viewer/256.js

This file was deleted.

2 changes: 2 additions & 0 deletions client/public/hcs-image-viewer/96.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/public/hcs-image-viewer/hcs-image-inject.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/public/hcs-image-viewer/hcs-image.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function HcsImageChannelsControl (
{pending && (<Icon type="loading" style={{marginLeft: 5}} />)}
</span>
<Checkbox
onChange={() => hcsViewerState.toggleChannelsLock(channelsLocked)}
onChange={(e) => hcsViewerState.setChannelsLocked(e.target.checked)}
checked={channelsLocked}
>
Lock channels
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class ViewerState {
identifiers = [],
channels = [],
channelsVisibility = [],
channelsLocked,
lockChannels,
globalSelection = {},
globalDimensions = [],
pixelValues = [],
Expand Down Expand Up @@ -213,8 +213,8 @@ class ViewerState {
* updated channels options
* @type {ChannelOptions[]}
*/
if (channelsLocked !== undefined) {
this.channelsLocked = channelsLocked;
if (lockChannels !== undefined) {
this.channelsLocked = lockChannels;
}
const updatedChannels = [];
for (let c = 0; c < identifiers.length; c++) {
Expand Down Expand Up @@ -297,9 +297,10 @@ class ViewerState {
};

@action
toggleChannelsLock = (channelsLocked) => {
if (this.viewer) {
this.channelsLocked = !channelsLocked;
setChannelsLocked = (channelsLocked) => {
if (this.viewer && typeof this.viewer.setLockChannels === 'function') {
this.channelsLocked = channelsLocked;
this.viewer.setLockChannels(channelsLocked);
}
};

Expand Down
25 changes: 18 additions & 7 deletions hcs-image-viewer/src/lib/state/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import reducer from './reducer';
import actions from './actions';
import useSource from './utilities/use-source';
import useViewerState from './viewer-state';
import ViewerStateActions from './viewer-state/actions';
import viewerActions from './viewer-state/actions';

export { default as HCSImageContext } from './context';

Expand Down Expand Up @@ -47,40 +47,51 @@ function useHCSImageState() {
}, [dispatch]);
const setImageViewportLoaded = useCallback((options) => {
dispatch({ type: actions.setImageViewportLoaded, ...options });
}, [dispatch]);
viewerDispatch({ type: viewerActions.setLoaded });
}, [dispatch, viewerDispatch]);
const setImageViewportLoading = useCallback(() => {
viewerDispatch({ type: viewerActions.setLoading });
}, [viewerDispatch]);
const setChannelProperties = useCallback((channel, properties) => {
viewerDispatch({ type: ViewerStateActions.setChannelProperties, channel, properties });
viewerDispatch({ type: viewerActions.setChannelProperties, channel, properties });
}, [viewerDispatch]);
const setColorMap = useCallback((colorMap) => {
viewerDispatch({ type: ViewerStateActions.setColorMap, colorMap });
viewerDispatch({ type: viewerActions.setColorMap, colorMap });
}, [viewerDispatch]);
const setLensEnabled = useCallback((enabled) => {
viewerDispatch({ type: ViewerStateActions.setLensEnabled, lensEnabled: enabled });
viewerDispatch({ type: viewerActions.setLensEnabled, lensEnabled: enabled });
}, [viewerDispatch]);
const setLensChannel = useCallback((channel) => {
viewerDispatch({ type: ViewerStateActions.setLensChannel, lensChannel: channel });
viewerDispatch({ type: viewerActions.setLensChannel, lensChannel: channel });
}, [viewerDispatch]);
const setGlobalPosition = useCallback((position) => {
viewerDispatch({ type: ViewerStateActions.setGlobalPosition, position });
viewerDispatch({ type: viewerActions.setGlobalPosition, position });
}, [viewerDispatch]);
const setLockChannels = useCallback((lock) => {
viewerDispatch({ type: viewerActions.setLockChannels, lock });
}, [viewerDispatch]);
const callbacks = useMemo(() => ({
setData,
setImage,
setImageViewportLoading,
setImageViewportLoaded,
setChannelProperties,
setColorMap,
setLensEnabled,
setLensChannel,
setGlobalPosition,
setLockChannels,
}), [
setData,
setImage,
setImageViewportLoading,
setImageViewportLoaded,
setChannelProperties,
setColorMap,
setLensEnabled,
setLensChannel,
setGlobalPosition,
setLockChannels,
]);
return {
callbacks,
Expand Down
2 changes: 2 additions & 0 deletions hcs-image-viewer/src/lib/state/viewer-state/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
export default {
setDefault: 'set-default',
setLoading: 'set-loading',
setLoaded: 'set-loaded',
setError: 'set-error',
setChannelProperties: 'set-channel-properties',
setColorMap: 'set-color-map',
setLensChannel: 'set-lens-channel',
setLensEnabled: 'set-lens-enabled',
setGlobalPosition: 'set-global-position',
setLockChannels: 'set-lock-channels',
};
1 change: 0 additions & 1 deletion hcs-image-viewer/src/lib/state/viewer-state/fetch-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ export default async function fetchInfo(loader, metadata, selections, globalPosi
const channels = Channels.map(mapChannel);
const [xSlice, ySlice, zSlice] = getBoundingCube(loader);
return {
identifiers: channels.map((name, index) => `${name || 'channel'}-${index}`),
channels,
selections: currentSelections,
useLens,
Expand Down
4 changes: 3 additions & 1 deletion hcs-image-viewer/src/lib/state/viewer-state/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default function init() {
globalSelection: undefined,
colors: [],
domains: [],
realDomains: [],
contrastLimits: [],
useLens: false,
useColorMap: false,
Expand All @@ -44,5 +45,6 @@ export default function init() {
metadata: undefined,
loader: [],
error: undefined,
lockChannels: false,
};
};
}
82 changes: 82 additions & 0 deletions hcs-image-viewer/src/lib/state/viewer-state/lock-channels-state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2017-2022 EPAM Systems, Inc. (https://www.epam.com/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

const EMPTY_ARRAY = [];

export default function lockChannelsState(state, channelsInfo) {
const {
lockChannels = false,
channels: currentChannels = EMPTY_ARRAY,
colors: currentColors = EMPTY_ARRAY,
domains: currentDomains = EMPTY_ARRAY,
contrastLimits: currentContrastLimits = EMPTY_ARRAY,
channelsVisibility: currentChannelsVisibility = EMPTY_ARRAY,
} = state || {};
const {
channels = EMPTY_ARRAY,
colors = EMPTY_ARRAY,
domains = EMPTY_ARRAY,
contrastLimits = EMPTY_ARRAY,
...rest
} = channelsInfo || {};
if (!lockChannels) {
return {
...rest,
channels,
colors,
domains,
contrastLimits,
realDomains: domains.slice(),
channelsVisibility: channels.map(() => true),
};
}
const currentChannelNames = currentChannels.slice();
const lockedChannels = [];
for (let c = 0; c < channels.length; c += 1) {
const currentChannelIndex = currentChannelNames.indexOf(channels[c]);
if (currentChannelIndex === -1) {
lockedChannels.push({
channel: channels[c],
color: colors[c],
domain: domains[c],
realDomain: domains[c].slice(),
contrastLimits: contrastLimits[c],
visibility: true,
});
} else {
currentChannelNames.splice(currentChannelIndex, 1, undefined);
lockedChannels.push({
channel: channels[c],
color: currentColors[currentChannelIndex] || colors[c],
domain: currentDomains[currentChannelIndex] || domains[c],
realDomain: domains[c].slice(),
contrastLimits: currentContrastLimits[currentChannelIndex] || contrastLimits[c],
visibility: currentChannelsVisibility[currentChannelIndex] === undefined
? true
: currentChannelsVisibility[currentChannelIndex],
});
}
}
return {
...rest,
channels: lockedChannels.map((o) => o.channel),
colors: lockedChannels.map((o) => o.color),
domains: lockedChannels.map((o) => o.domain),
realDomains: lockedChannels.map((o) => o.realDomain),
contrastLimits: lockedChannels.map((o) => o.contrastLimits),
channelsVisibility: lockedChannels.map((o) => o.visibility),
};
}
45 changes: 40 additions & 5 deletions hcs-image-viewer/src/lib/state/viewer-state/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import ViewerStateActions from './actions';
import changeChannelProperties from './change-channel-properties';
import lockChannelsState from './lock-channels-state';
import { GlobalDimensionFields } from '../constants';

const EMPTY_ARRAY = [];
Expand All @@ -26,6 +27,9 @@ export default function reducer(state, action) {
case ViewerStateActions.setLoading: {
return { ...state, pending: true, error: undefined };
}
case ViewerStateActions.setLoaded: {
return { ...state, pending: false };
}
case ViewerStateActions.setChannelProperties: {
const { channel, properties } = action;
return changeChannelProperties(state, channel, properties);
Expand Down Expand Up @@ -97,13 +101,43 @@ export default function reducer(state, action) {
}
return state;
}
case ViewerStateActions.setLockChannels: {
const { lock } = action;
const {
contrastLimits = EMPTY_ARRAY,
realDomains = EMPTY_ARRAY,
} = state;
const newState = {
...state,
lockChannels: lock,
};
if (!lock) {
newState.domains = realDomains.slice();
newState.contrastLimits = contrastLimits.map((limit, index) => {
const domain = realDomains[index];
if (domain && Array.isArray(domain) && domain.length === 2) {
const [cFrom, cTo, ...limitRest] = limit;
const [dFrom, dTo] = domain;
const correct = (l) => Math.max(dFrom, Math.min(dTo, l));
return [
correct(cFrom),
correct(cTo),
...limitRest,
];
}
return limit;
});
}
return newState;
}
case ViewerStateActions.setDefault: {
const {
identifiers = EMPTY_ARRAY,
channels = EMPTY_ARRAY,
channelsVisibility = EMPTY_ARRAY,
selections = EMPTY_ARRAY,
colors = EMPTY_ARRAY,
domains = EMPTY_ARRAY,
realDomains = domains.slice(),
contrastLimits = EMPTY_ARRAY,
useLens = false,
useColorMap = false,
Expand All @@ -120,17 +154,19 @@ export default function reducer(state, action) {
globalDimensions = EMPTY_ARRAY,
metadata,
loader,
} = action;
} = lockChannelsState(state, action);
return {
identifiers,
...state,
identifiers: channels.map((name, index) => `${name || 'channel'}-${index}`),
channels,
channelsVisibility: channels.map(() => true),
channelsVisibility,
selections,
builtForSelections: selections,
globalSelection: (selections || [])[0],
pixelValues: new Array((selections || []).length).fill('-----'),
colors,
domains,
realDomains,
contrastLimits,
useLens,
useColorMap,
Expand All @@ -145,7 +181,6 @@ export default function reducer(state, action) {
isRGB,
shapeIsInterleaved,
globalDimensions,
pending: false,
error: undefined,
metadata,
loader,
Expand Down
11 changes: 11 additions & 0 deletions hcs-image-viewer/src/lib/viewer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,17 @@ class Viewer {
setGlobalTimePosition(time) {
return this.setGlobalPosition({ t: time });
}

setLockChannels(lock) {
return new Promise((resolve, reject) => {
this.waitForInitialization()
.then(() => {
this.getCallback('setLockChannels')(lock);
resolve();
})
.catch(reject);
});
}
}

export default Viewer;
6 changes: 6 additions & 0 deletions hcs-image-viewer/src/lib/viewer/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ function HCSImageViewer(
}
}, [callbacks, onRegisterStateActions]);
const {
setImageViewportLoading,
setImageViewportLoaded,
} = callbacks || {};
const {
Expand All @@ -108,6 +109,11 @@ function HCSImageViewer(
lensEnabled,
lensChannel,
} = viewerState;
useEffect(() => {
if (typeof setImageViewportLoading === 'function') {
setImageViewportLoading();
}
}, [selections, loader, setImageViewportLoading]);
const [viewState, setViewState] = useState(undefined);
useEffect(() => {
if (loader && loader.length && size && size.width && size.height) {
Expand Down

0 comments on commit ac0dc51

Please sign in to comment.