Skip to content

Commit

Permalink
Preview for the HCS images (#2489) - Stack panel
Browse files Browse the repository at this point in the history
  • Loading branch information
ZMaratovna authored and rodichenko committed Feb 17, 2022
1 parent 27a8caf commit 63ea86f
Show file tree
Hide file tree
Showing 9 changed files with 316 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,57 +20,56 @@ import {Icon} from 'antd';
import Channel from './channel';
import styles from './hcs-image-controls.css';

@inject('hcsViewerState')
@observer
class HcsImageChannelsControl extends React.Component {
render () {
const {hcsViewerState = {}} = this.props;
const {
channels = [],
pending
} = hcsViewerState;
if (pending && channels.length === 0) {
return (
<div className={styles.channels}>
<i className="cp-text-not-important">Loading channels...</i>
</div>
);
}
if (channels.length === 0) {
return null;
}
function HcsImageChannelsControl (
{
hcsViewerState
}
) {
const {
channels = [],
pending
} = hcsViewerState || {};
if (pending && channels.length === 0) {
return (
<div className={styles.channels}>
<div className={styles.header}>
Channels:
{pending && (<Icon type="loading" style={{marginLeft: 5}} />)}
</div>
{
channels.map(channel => (
<Channel
key={channel.identifier}
identifier={channel.identifier}
name={channel.name}
visible={channel.visible}
color={channel.color}
domain={channel.domain}
contrastLimits={channel.contrastLimits}
loading={pending}
onVisibilityChanged={
(visible) => hcsViewerState.changeChannelVisibility(channel, visible)
}
onContrastLimitsChanged={
(limits) => hcsViewerState.changeChannelContrastLimits(channel, limits)
}
onColorChanged={
(color) => hcsViewerState.changeChannelColor(channel, color)
}
/>
))
}
<i className="cp-text-not-important">Loading channels...</i>
</div>
);
}
if (channels.length === 0) {
return null;
}
return (
<div className={styles.channels}>
<div className={styles.header}>
Channels:
{pending && (<Icon type="loading" style={{marginLeft: 5}} />)}
</div>
{
channels.map(channel => (
<Channel
key={channel.identifier}
identifier={channel.identifier}
name={channel.name}
visible={channel.visible}
color={channel.color}
domain={channel.domain}
contrastLimits={channel.contrastLimits}
loading={pending}
onVisibilityChanged={
(visible) => hcsViewerState.changeChannelVisibility(channel, visible)
}
onContrastLimitsChanged={
(limits) => hcsViewerState.changeChannelContrastLimits(channel, limits)
}
onColorChanged={
(color) => hcsViewerState.changeChannelColor(channel, color)
}
/>
))
}
</div>
);
}

export default HcsImageChannelsControl;
export default inject('hcsViewerState')(observer(HcsImageChannelsControl));
81 changes: 39 additions & 42 deletions client/src/components/special/hcs-image/hcs-image-controls/lens.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,48 +20,45 @@ import {Checkbox, Select} from 'antd';

import styles from './hcs-image-controls.css';

@inject('hcsViewerState')
@observer
class HcsLensControl extends React.Component {
render () {
const {hcsViewerState = {}} = this.props;
const {
channels = [],
useLens,
lensEnabled,
lensChannel,
pending
} = hcsViewerState;
if (useLens && channels.length > 1) {
return (
<div className={styles.lensContainer}>
<Checkbox
disabled={pending}
checked={lensEnabled}
onChange={(e) => hcsViewerState.changeLensMode(e.target.checked)}
>
Lens
</Checkbox>
<Select
disabled={pending || !lensEnabled}
style={{flex: '1 1 auto'}}
onChange={(channelIndex) => hcsViewerState.changeLensChannel(channelIndex)}
value={lensChannel >= 0 ? `${lensChannel}` : undefined}
>
{channels.map((channel) => (
<Select.Option
key={channel.identifier}
value={`${channel.index}`}
>
{channel.name}
</Select.Option>))
}
</Select>
</div>
);
}
return null;
function HcsLensControl (
hcsViewerState
) {
const {
channels = [],
useLens,
lensEnabled,
lensChannel,
pending
} = hcsViewerState || {};
if (useLens && channels.length > 1) {
return (
<div className={styles.lensContainer}>
<Checkbox
disabled={pending}
checked={lensEnabled}
onChange={(e) => hcsViewerState.changeLensMode(e.target.checked)}
>
Lens
</Checkbox>
<Select
disabled={pending || !lensEnabled}
style={{flex: '1 1 auto'}}
onChange={(channelIndex) => hcsViewerState.changeLensChannel(channelIndex)}
value={lensChannel >= 0 ? `${lensChannel}` : undefined}
>
{channels.map((channel) => (
<Select.Option
key={channel.identifier}
value={`${channel.index}`}
>
{channel.name}
</Select.Option>))
}
</Select>
</div>
);
}
return null;
}

export default HcsLensControl;
export default inject('hcsViewerState')(observer(HcsLensControl));
2 changes: 2 additions & 0 deletions client/src/components/special/hcs-image/hcs-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import SourceState from './utilities/source-state';
import HcsImageControls from './hcs-image-controls';
import LoadingView from '../LoadingView';
import styles from './hcs-image.css';
import HcsZPositionSelector from './hcs-z-position-selector';

@observer
class HcsImage extends React.PureComponent {
Expand Down Expand Up @@ -613,6 +614,7 @@ class HcsImage extends React.PureComponent {
selectedTimePoint={timePointId}
onChangeTimePoint={this.changeTimePoint}
/>
<HcsZPositionSelector />
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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.
*/

.container {
padding: 5px;
overflow: hidden;
}

.container .slider-container {
max-height: 200px;
padding: 14px 0;
display: flex;
flex-direction: row;
justify-content: center;
}

.container.horizontal .slider-container {
width: 100%;
display: block;
padding: 0 10px;
}

.title {
font-weight: bold;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* 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.
*/

import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import {Slider} from 'antd';
import {inject, observer} from 'mobx-react';

import {MAX_Z_POSITIONS_TO_DISPLAY} from '../utilities/constants';
import styles from './hcs-z-position-selector.css';

const SelectorType = {
vertical: 'vertical',
horizontal: 'horizontal'
};

const MAX_HEIGHT_PER_TICK = 45;

function zPositionSorter (a, b) {
return a.z - b.z;
}

function HcsZPositionSelector (props) {
const {
className,
type = SelectorType.horizontal,
hcsViewerState
} = props;
if (!hcsViewerState) {
return null;
}
const {
availableZPositions: positions = [],
imageZPosition: value
} = hcsViewerState;
const onChange = z => hcsViewerState.changeGlobalZPosition(z);
if (positions.length > 1) {
const sorted = positions
.slice()
.sort(zPositionSorter);
const tipFormatter = z => {
const item = sorted.find(o => o.z === z);
if (item) {
return item.title;
}
return null;
};
const [first] = sorted;
const last = sorted[sorted.length - 1];
const firstTitleLength = (first.title || '').length;
const lastTitleLength = (last.title || '').length;
const getPadding = titleLength => `${Math.ceil(titleLength / 2)}em`;
const max = last.z;
const min = first.z;
let marks = {
[first.z]: first.title,
[last.z]: last.title
};
if (positions.length <= MAX_Z_POSITIONS_TO_DISPLAY) {
marks = positions.reduce((points, {z, title}) => ({
...points,
[z]: title
}), {});
}
const verticalStyle = {
height: positions.length * MAX_HEIGHT_PER_TICK
};
const horizontalStyle = {
paddingLeft: getPadding(firstTitleLength),
paddingRight: getPadding(lastTitleLength)
};
return (
<div
className={
classNames(
className,
styles.container,
{
[styles.horizontal]: type === SelectorType.horizontal
}
)}
>
<div
className={styles.title}
>
Z-plane
</div>
<div
className={styles.sliderContainer}
style={
type === SelectorType.vertical
? verticalStyle
: horizontalStyle
}
>
<Slider
className={'cp-hcs-z-position-slider'}
vertical={type === SelectorType.vertical}
included={false}
dots
value={value}
marks={marks}
max={max}
min={min}
step={1}
onChange={onChange}
tipFormatter={tipFormatter}
/>
</div>
</div>
);
}
return null;
}

HcsZPositionSelector.propTypes = {
className: PropTypes.string,
type: PropTypes.oneOf([
SelectorType.vertical,
SelectorType.horizontal
])
};

HcsZPositionSelector.defaultProps = {
type: SelectorType.horizontal
};

const selector = inject('hcsViewerState')(observer(HcsZPositionSelector));

selector.Type = SelectorType;

export default selector;
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
export const OME_TIFF_FILE_NAME = 'data.ome.tiff';
export const OFFSETS_JSON_FILE_NAME = 'data.offsets.json';
export const WELLS_MAP_FILE_NAME = 'wells_map.json';
export const MAX_Z_POSITIONS_TO_DISPLAY = 5;
Loading

0 comments on commit 63ea86f

Please sign in to comment.