Skip to content

Commit

Permalink
integrate api
Browse files Browse the repository at this point in the history
  • Loading branch information
sanglevinh committed Oct 12, 2023
1 parent fd32d47 commit e78fe43
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 50 deletions.
31 changes: 31 additions & 0 deletions frontend/src/api/outputs/Outputs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import axios from 'utils/axios'
import { PlotMetaData } from 'store/slice/DisplayData/DisplayDataType'
import { BASE_URL } from 'const/API'
import {StatusROI} from "../../components/Workspace/Visualize/Plot/ImagePlot";

export type TimeSeriesData = {
[key: string]: {
Expand Down Expand Up @@ -173,6 +174,36 @@ export async function deleteRoiApi(
return response.data
}

export async function commitRoiApi(
path: string,
workspace_id: number,
): Promise<{ data: HTMLData; meta?: PlotMetaData }> {
const response = await axios.post(
`${BASE_URL}/outputs/image/${path}/commit_edit?workspace_id=${workspace_id}`
)
return response.data
}

export async function cancelRoiApi(
path: string,
workspace_id: number,
): Promise<{ data: HTMLData; meta?: PlotMetaData }> {
const response = await axios.post(
`${BASE_URL}/outputs/image/${path}/cancel_edit?workspace_id=${workspace_id}`
)
return response.data
}

export async function getStatusRoi(
path: string,
workspace_id: number,
): Promise<StatusROI> {
const response = await axios.post(
`${BASE_URL}/outputs/image/${path}/status?workspace_id=${workspace_id}`
)
return response.data
}

export type LineData = number[][]

export async function getLineDataApi(
Expand Down
152 changes: 102 additions & 50 deletions frontend/src/components/Workspace/Visualize/Plot/ImagePlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ import {
selectingImageArea,
setImageItemClikedDataId,
} from 'store/slice/VisualizeItem/VisualizeItemActions'
import { addRoiApi, deleteRoiApi, mergeRoiApi } from 'api/outputs/Outputs'
import {addRoiApi, cancelRoiApi, commitRoiApi, deleteRoiApi, getStatusRoi, mergeRoiApi} from 'api/outputs/Outputs'
import { isTimeSeriesItem } from 'store/slice/VisualizeItem/VisualizeItemUtils'
import { selectCurrentWorkspaceId } from 'store/slice/Workspace/WorkspaceSelector'
import Loading from "../../../common/Loading";
Expand All @@ -83,6 +83,12 @@ interface PointClick {
z: number
}

export type StatusROI = {
temp_add_roi: number[]
temp_delete_roi: number[]
temp_merge_roi: number[]
}

const WIDTH_CHARTJS = 321
const INIT_WIDTH_ROI = 30

Expand Down Expand Up @@ -177,15 +183,11 @@ const ImagePlotChart = React.memo<{
imageDataEqualtyFn,
)

const [isAddRoi, setIsAddRoi] = useState(false)
const [loadingApi, setLoadingApi] = useState(false)

const [roiDataState, setRoiDataState] = useState(roiData)

const [pointClick, setPointClick] = useState<PointClick[]>([])

const itemsVisual = useSelector(selectVisualizeItems)

const showticklabels = useSelector(selectImageItemShowticklabels(itemId))
const showline = useSelector(selectImageItemShowLine(itemId))
const zsmooth = useSelector(selectImageItemZsmooth(itemId))
Expand All @@ -199,10 +201,14 @@ const ImagePlotChart = React.memo<{
const height = useSelector(selectVisualizeItemHeight(itemId))

const [sizeDrag, setSizeDrag] = useState(initSizeDrag)

const [startDragAddRoi, setStartDragAddRoi] = useState(false)
const [action, setAction] = React.useState('')
const [positionDrag, setChangeSize] = useState<PositionDrag | undefined>()
const [statusRoi, setStatusRoi] = useState<StatusROI>({
temp_add_roi: [],
temp_delete_roi: [],
temp_merge_roi: []
})

const outputKey: string | null = useSelector(selectRoiItemOutputKeys(itemId))

Expand All @@ -220,12 +226,6 @@ const ImagePlotChart = React.memo<{
setRoiDataState(roiData)
}, [roiData])

// useEffect(() => {
// onCancel()
// onCancelAdd()
// //eslint-disable-next-line react-hooks/exhaustive-deps
// }, [outputKey, roiFilePath])

const data = React.useMemo(
() => [
{
Expand Down Expand Up @@ -260,16 +260,32 @@ const ImagePlotChart = React.memo<{
z: roiDataState,
type: 'heatmap',
name: 'roi',
hovertemplate: isAddRoi ? 'none' : 'cell id: %{z}',
hovertemplate: action === 'Add ROI' ? 'none' : 'cell id: %{z}',
// hoverinfo: isAddRoi || pointClick.length ? 'none' : undefined,
colorscale: [...Array(timeDataMaxIndex + 1)].map((_, i) => {
const new_i = Math.floor(((i % 10) * 10 + i / 10) % 100)
const offset: number = i / timeDataMaxIndex
const rgba = colorscaleRoi[new_i]
// const rgba = [52, 113, 235, 1]
const hex = rgba2hex(rgba, roiAlpha)
if(pointClick.find(e => e.z === i)) {
return [offset, action === 'Delete ROI' ? '#ffffff' : '#e134eb']
if(!action) {
if(statusRoi.temp_delete_roi.includes(i)) return [offset, '#ffffff']
if(statusRoi.temp_merge_roi.includes(i)) return [offset, '#e134eb']
if(statusRoi.temp_add_roi.includes(i)) return [offset, '#3483eb']
}
if(action === 'Add ROI' ) {
if(statusRoi.temp_delete_roi.includes(i)) return [offset, '#ffffff']
if(statusRoi.temp_add_roi.includes(i)) return [offset, '#3483eb']
if(statusRoi.temp_merge_roi.includes(i)) return [offset, '#e134eb']
}
if(action === 'Delete ROI') {
if(pointClick.find(e => e.z === i) || statusRoi.temp_delete_roi.includes(i)) return [offset, '#ffffff']
if(statusRoi.temp_add_roi.includes(i)) return [offset, '#3483eb']
if(statusRoi.temp_merge_roi.includes(i)) return [offset, '#e134eb']
}
if(action === 'Merge ROI') {
if(statusRoi.temp_delete_roi.includes(i)) return [offset, '#ffffff']
if(pointClick.find(e => e.z === i) || statusRoi.temp_merge_roi.includes(i)) return [offset, '#e134eb']
if(statusRoi.temp_add_roi.includes(i)) return [offset, '#3483eb']
}
return [offset, hex]
}),
Expand All @@ -290,14 +306,28 @@ const ImagePlotChart = React.memo<{
timeDataMaxIndex,
roiAlpha,
alpha,
isAddRoi,
pointClick,
action
action,
statusRoi,
],
)

const [selectMode, setSelectMode] = React.useState(false)
const [edit, setEdit] = React.useState(false)
const [selectMode, setSelectMode] = useState(false)
const [edit, setEdit] = useState(false)

const fetchStatusRoi = async () => {
if(!roiFilePath || workspaceId === undefined) return
try {
const data = await getStatusRoi(roiFilePath, workspaceId)
setStatusRoi(data as StatusROI)
}
catch{}
}

useEffect(() => {
fetchStatusRoi()
//eslint-disable-next-line
}, [roiFilePath, workspaceId, edit])

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSelectMode(event.target.checked)
Expand Down Expand Up @@ -345,7 +375,7 @@ const ImagePlotChart = React.memo<{
},
}),
//eslint-disable-next-line react-hooks/exhaustive-deps
[meta, showgrid, showline, showticklabels, width, height, selectMode, isAddRoi],
[meta, showgrid, showline, showticklabels, width, height, selectMode, action],
)

const saveFileName = useSelector(selectVisualizeSaveFilename(itemId))
Expand Down Expand Up @@ -387,37 +417,44 @@ const ImagePlotChart = React.memo<{
const setSelectRoi = (point: PointClick) => {
if(!['Merge ROI', 'Delete ROI'].includes(action)) return
if (isNaN(Number(point.z))) return

let newPoints
if(statusRoi.temp_delete_roi.includes(point.z)) {
return
}
const check = pointClick.findIndex(item => item.z === point.z)
if(check < 0) {
newPoints = [...pointClick, point]
}
else {
newPoints = pointClick.filter(item => item.z !== point.z)
}

// const newRoi = roiDataState.map((roi) => {
// return roi.map((element) => {
// if (newPoints.some((p) => p.z === element)) {
// return -1
// }
// return element
// })
// })
setPointClick(newPoints)
// setRoiDataState(newRoi)
}

const onCancel = () => {
const onCancel = async () => {
if(!roiFilePath || workspaceId === undefined) return
setEdit(false)
setAction('')
setPointClick([])
setRoiDataState(roiData)
setLoadingApi(true)
try {
await cancelRoiApi(roiFilePath, workspaceId)
}
finally {
workspaceId && dispatch(getRoiData({ path: roiFilePath, workspaceId }))
setStatusRoi({
temp_add_roi: [],
temp_delete_roi: [],
temp_merge_roi: []
})
setLoadingApi(false)
}
}

const addRoi = () => {
setEdit(false)
setAction('')
setIsAddRoi(true)
setAction('Add ROI')
}

const editRoi = () => {
Expand All @@ -427,7 +464,6 @@ const ImagePlotChart = React.memo<{
const onCancelAdd = () => {
setAction('')
setEdit(true)
setIsAddRoi(false)
setSizeDrag(initSizeDrag)
setChangeSize(undefined)
setPointClick([])
Expand Down Expand Up @@ -486,9 +522,7 @@ const ImagePlotChart = React.memo<{

const addOrSelectRoi = async () => {
if (!roiFilePath || loadingApi) return
setEdit(false)
if(isAddRoi) {
setAction('')
if(action === 'Add ROI') {
setLoadingApi(true)
const sizeX = roiDataState[0].length - 1
const sizeY = roiDataState.length - 1
Expand Down Expand Up @@ -521,7 +555,7 @@ const ImagePlotChart = React.memo<{
})
} catch {}
setLoadingApi(false)
onCancel()
setPointClick([])
workspaceId && dispatch(getRoiData({ path: roiFilePath, workspaceId }))
}
else if(action === 'Delete ROI') {
Expand All @@ -534,10 +568,11 @@ const ImagePlotChart = React.memo<{
})
} catch {}
setLoadingApi(false)
onCancel()
setPointClick([])
workspaceId && dispatch(getRoiData({ path: roiFilePath, workspaceId }))
}
resetTimeSeries()
setEdit(true)
}

const onMergeRoi = async () => {
Expand All @@ -552,6 +587,24 @@ const ImagePlotChart = React.memo<{
setAction('Delete ROI')
}

const onCommitRoi = async () => {
if(!roiFilePath || workspaceId === undefined) return
setLoadingApi(true)
try {
await commitRoiApi(roiFilePath, workspaceId)
}
catch {}
finally {
workspaceId && dispatch(getRoiData({ path: roiFilePath, workspaceId }))
setStatusRoi({
temp_add_roi: [],
temp_delete_roi: [],
temp_merge_roi: []
})
setLoadingApi(false)
}
}

const resetTimeSeries = () => {
if (itemsVisual) {
Object.keys(itemsVisual).forEach((item) => {
Expand All @@ -568,15 +621,11 @@ const ImagePlotChart = React.memo<{
}

const renderActionRoi = () => {
// if (!roiDataState?.length || outputKey !== 'cell_roi') return null
// if (!isAddRoi) {
// return <LinkDiv onClick={addRoi}>Add ROI</LinkDiv>
// }

if(isAddRoi || action) {
if(action) {
return (
<>
{!isAddRoi ?
{ action !== 'Add ROI' ?
<BoxDiv>
ROI Selecteds: [{pointClick.map(item => item.z).join(',')}]
</BoxDiv>
Expand All @@ -587,12 +636,12 @@ const ImagePlotChart = React.memo<{
>
<LinkDiv
sx={{
color: action ? action === 'Delete ROI' ? '#F84E1B' : '#6619A9' : 'default',
color: action === 'Delete ROI' ? '#F84E1B' : action === 'Merge ROI' ? '#6619A9' : 'default',
display: 'flex',
gap: 1
}}
>
{isAddRoi ? '[Add ROI]' : `[${action}]`}
{`[${action}]`}
</LinkDiv>
<LinkDiv
onClick={onCancelAdd}
Expand All @@ -617,6 +666,8 @@ const ImagePlotChart = React.memo<{
return null
}

if(!statusRoi) return null

return (
<div>
{
Expand Down Expand Up @@ -659,6 +710,7 @@ const ImagePlotChart = React.memo<{
<BoxWrapper>
<LinkDiv
sx={{ color: '#32A919', opacity: loadingApi ? 0.5 : 1 }}
onClick={onCommitRoi}
>
Commit Edit
</LinkDiv>
Expand All @@ -683,7 +735,7 @@ const ImagePlotChart = React.memo<{
onClick={onChartClick}
onSelecting={onSelecting}
/>
{isAddRoi ? (
{action === 'Add ROI' ? (
<DivAddRoi>
<DivSvg
onMouseLeave={onMouseUpDragAddRoi}
Expand Down

0 comments on commit e78fe43

Please sign in to comment.