Skip to content

Commit

Permalink
Merge pull request #42 from bnmajor/change-datasets
Browse files Browse the repository at this point in the history
feat(toggle data): Add ability to toggle current data
  • Loading branch information
thewtex committed Feb 22, 2022
2 parents 6a401a1 + 9c32f79 commit 86004e8
Show file tree
Hide file tree
Showing 19 changed files with 648 additions and 180 deletions.
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@kitware/vtk.js": "^19.0.2",
"babel-loader": "^8.2.3",
"itk-viewer-icons": "^11.11.2",
"itk-viewer-material-ui": "^0.1.0",
"itk-viewer-material-ui": "^0.1.3",
"material-ui": "^0.20.2",
"ndarray-pack": "^1.2.1",
"react": "^17.0.2",
Expand Down
128 changes: 128 additions & 0 deletions client/src/ImageSelector.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import React, { useEffect, useState } from 'react'
import { useActor } from '@xstate/react'
import { Button, LinearProgress, TextField } from '@mui/material'
import { ArrowBack, ArrowForward } from '@mui/icons-material'
import {
encodeScijsArray, fetchJSON, saveStateSettings,
updateLabelSettings, updateStateSettings
} from './utils'
import './style.css'
import { debounce } from 'lodash'

function ImageSelector(props) {
const { service } = props
const [state, send] = useActor(service)
const [imageCount, setImageCount] = useState({current: 1, total: 1})
const [changingImage, setChangingImage] = useState(false);
const lastAddedData = state.context.layers.lastAddedData;
const name = state.context.images.selectedName;
const component = state.context.images.selectedComponent;
const actorContext = state.context.images.actorContext.get(name)

useEffect(async() => {
const counts = await fetchJSON(`../tensorboard_plugin_3d/images/count`);
setImageCount(counts);
}, [])

useEffect(() => {
if (actorContext?.labelImageName && actorContext?.labelImageToggleWeight)
updateLabelSettings(name, actorContext.labelImageToggleWeight, send)
}, [actorContext?.labelImageName])

useEffect(() => {
if (name && component >= 0)
updateStateSettings(name, component, send);
}, [name, component])

const changeImage = async (idx) => {
if (idx < 1)
idx = 1
if (idx > imageCount.total)
idx = imageCount.total

saveStateSettings(state.context);
const params = new URLSearchParams({idx})
setChangingImage(true);
const img_data = await fetchJSON(`../tensorboard_plugin_3d/images/current?${params}`)
.then(response => {
let image_data = {image: encodeScijsArray(response.image)}
if (response.label) {
image_data.labelImage = encodeScijsArray(response.label)
}
return image_data
})
window.itkVtkViewer.createViewer(
document.querySelector('.content'),
{
...img_data,
rotate: state.context.main.rotateEnabled,
config: { ...state.context },
}).finally(() => setChangingImage(false))
}

const debouncedChangeImage = debounce((idx) => {changeImage(idx)}, [500])

const handleChange = (value) => {
value = Math.max(Math.min(value, imageCount.total), 1)
const diff = value - imageCount.current
if (diff) {
setImageCount({...imageCount, current: imageCount.current + diff})
debouncedChangeImage(imageCount.current + diff)
}
}

return (
<div className={(!lastAddedData || imageCount.total < 2) && "hidden"}>
<div className='imageToggle'>
<Button
variant="contained"
size="small"
style={{marginRight: '3px'}}
className={"arrowButtons"}
disabled={imageCount.current === 1 || changingImage}
onClick={() => {
setImageCount({...imageCount, current: imageCount.current-1})
debouncedChangeImage(imageCount.current-1)
}}
>
<ArrowBack />
</Button>
<div className="imageSelector">
Image
<TextField
type="number"
className="imageInput"
InputLabelProps={{
shrink: true
}}
variant="filled"
size="small"
margin="dense"
disabled={changingImage}
value={imageCount.current}
onChange={(e) => {handleChange(e.target.value)}}
/>
of {imageCount.total}
</div>
<Button
variant="contained"
size="small"
style={{marginLeft: '3px'}}
className={"arrowButtons"}
disabled={imageCount.current === imageCount.total || changingImage}
onClick={() => {
setImageCount({...imageCount, current: imageCount.current+1})
debouncedChangeImage(imageCount.current+1)
}}
>
<ArrowForward />
</Button>
</div>
<div className={changingImage ? "" : "hidden"}>
<LinearProgress color="inherit" />
</div>
</div>
)
}

export default ImageSelector
27 changes: 4 additions & 23 deletions client/src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import materialUIMachineOptions from 'itk-viewer-material-ui/src/materialUIMachineOptions'
import modifiedCreateInterface from './main'
import ndarraypack from 'ndarray-pack'
import { encodeScijsArray, fetchJSON } from './utils'

const uiMachineOptions = { ...materialUIMachineOptions }

Expand All @@ -11,30 +11,11 @@ uiMachineOptions.actions = uiMachineActions

const container = document.querySelector('.content')

async function fetchJSON(url) {
const response = await fetch(url);
if (!response.ok) {
return null;
}
const data = response.json();
return data;
}

function encodeScijsArray(array){
const encoded = {
_rtype: 'ndarray',
_rdtype: array.dtype,
_rshape: array.shape,
_rvalue: array.data,
}
return encoded
}

async function createViewer() {
const img_data = await fetchJSON('../tensorboard_plugin_3d/images').then(response => {
let image_data = {image: encodeScijsArray(ndarraypack(response.image))}
const img_data = await fetchJSON('../tensorboard_plugin_3d/images/current').then(response => {
let image_data = {image: encodeScijsArray(response.image)}
if (response.label) {
image_data.labelImage = encodeScijsArray(ndarraypack(response.label))
image_data.labelImage = encodeScijsArray(response.label)
}
return image_data
})
Expand Down
4 changes: 3 additions & 1 deletion client/src/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import 'itk-viewer-material-ui/src/style.css'
import CollapseUIButton from 'itk-viewer-material-ui/src/CollapseUIButton'
import Panel from 'itk-viewer-material-ui/src/Panel'
import MainInterface from 'itk-viewer-material-ui/src/Main/MainInterface'
import LayersInterface from 'itk-viewer-material-ui/src/Layers/LayersInterface'
import ImagesInterface from 'itk-viewer-material-ui/src/Images/ImagesInterface'
import ImageSelector from './ImageSelector'
import WidgetsInterface from 'itk-viewer-material-ui/src/Widgets/WidgetsInterface'
import './style.css'
import LayersInterface from 'itk-viewer-material-ui/src/Layers/LayersInterface'

function modifiedCreateInterface(context) {
context.viewContainers = new Map()
Expand All @@ -33,6 +34,7 @@ function modifiedCreateInterface(context) {
<CollapseUIButton service={ context.service }/>
<Panel service={ context.service }>
<MainInterface />
<ImageSelector />
<LayersInterface />
<WidgetsInterface />
<ImagesInterface />
Expand Down
55 changes: 55 additions & 0 deletions client/src/style.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,58 @@
.css-1lpukdo {
padding: 0px !important;
background: rgba(128, 128, 128, 0.5) !important;
border: solid 3px rgba(255, 255, 255, 0.3) !important;
width: 125px;
}

.css-fi4tqy {
padding: 0px !important;
}

.css-q44vsa::before {
border-bottom: none;
}

.hidden {
display: none;
}

.imageInput {
width: 50px;
text-align-last: center;
margin: 0px !important;
}

.imageSelector {
display: flex;
justify-content: center;
align-items: center;
}

.imageToggle {
display: flex;
justify-content: space-between;
background-color: rgba(128, 128, 128, 0.5);
border-radius: 3px;
margin: 2px 0px;
align-items: center;
}

.layerIcon {
padding-left: 0px;
}

.layerLabelCommon {
margin-right: 5px;
}

.layersUIGroup {
margin-left: 0px;
width: 100%;
max-width: inherit;
}

.MuiDrawer-paper {
top: 35px !important;
max-width: 400px;
}

0 comments on commit 86004e8

Please sign in to comment.