From e22431668e0a437990d7c6ad683eaab164a7a7ee Mon Sep 17 00:00:00 2001 From: MichaelBuessemeyer <39529669+MichaelBuessemeyer@users.noreply.github.com> Date: Tue, 24 Mar 2020 14:23:02 +0100 Subject: [PATCH] Fix displayed segment (#4480) * use corect resolution for segment id look up * fix flow * add individual resolution to mouse position and put resolution in own column * rename resolution column, add changelog entry --- CHANGELOG.md | 4 +- .../model/bucket_data_handling/data_cube.js | 4 + .../view/right-menu/mapping_info_view.js | 100 +++++++++++++++--- 3 files changed, 93 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 276657ee56c..bd233e81d09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,15 +10,17 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md). [Commits](https://github.com/scalableminds/webknossos/compare/20.04.0...HEAD) ### Added -- +- Added the magnification used for determining the segment ids in the segmentation tab to the table of the tab [#4480](https://github.com/scalableminds/webknossos/pull/4480) ### Changed - Reported datasets can now overwrite existing ones that are reported as missing, this ignores the isScratch precedence. [#4465](https://github.com/scalableminds/webknossos/pull/4465) ### Fixed - Users only get tasks of datasets that they can access. [#4488](https://github.com/scalableminds/webknossos/pull/4488) +- Fixed the displayed segment ids in segmentation tab when "Render Missing Data Black" is turned off. [#4480](https://github.com/scalableminds/webknossos/pull/4480) ### Removed + - diff --git a/frontend/javascripts/oxalis/model/bucket_data_handling/data_cube.js b/frontend/javascripts/oxalis/model/bucket_data_handling/data_cube.js index abfa1b7de33..4df1110cf73 100644 --- a/frontend/javascripts/oxalis/model/bucket_data_handling/data_cube.js +++ b/frontend/javascripts/oxalis/model/bucket_data_handling/data_cube.js @@ -368,6 +368,10 @@ class DataCube { } } + hasDataAtPositionAndZoomStep(voxel: Vector3, zoomStep: number = 0) { + return this.getBucket(this.positionToZoomedAddress(voxel, zoomStep)).hasData(); + } + getDataValue(voxel: Vector3, mapping: ?Mapping, zoomStep: number = 0): number { const bucket = this.getBucket(this.positionToZoomedAddress(voxel, zoomStep)); const voxelIndex = this.getVoxelIndex(voxel, zoomStep); diff --git a/frontend/javascripts/oxalis/view/right-menu/mapping_info_view.js b/frontend/javascripts/oxalis/view/right-menu/mapping_info_view.js index 3b6dbebd7ef..3dc858c6532 100644 --- a/frontend/javascripts/oxalis/view/right-menu/mapping_info_view.js +++ b/frontend/javascripts/oxalis/view/right-menu/mapping_info_view.js @@ -16,7 +16,7 @@ import type { OxalisState, Mapping } from "oxalis/store"; import { calculateGlobalPos } from "oxalis/controller/viewmodes/plane_controller"; import { getMappingsForDatasetLayer } from "admin/admin_rest_api"; import { getPosition, getRequestLogZoomStep } from "oxalis/model/accessors/flycam_accessor"; -import { getSegmentationLayer } from "oxalis/model/accessors/dataset_accessor"; +import { getSegmentationLayer, getResolutions } from "oxalis/model/accessors/dataset_accessor"; import { getVolumeTracing } from "oxalis/model/accessors/volumetracing_accessor"; import { setLayerMappingsAction } from "oxalis/model/actions/dataset_actions"; import { setMappingEnabledAction } from "oxalis/model/actions/settings_actions"; @@ -45,6 +45,7 @@ type StateProps = {| activeViewport: OrthoView, activeCellId: number, isMergerModeEnabled: boolean, + renderMissingDataBlack: boolean, |}; type Props = {| ...OwnProps, ...StateProps |}; @@ -126,24 +127,74 @@ class MappingInfoView extends React.Component { } renderIdTable() { + const { + mapping, + isMappingEnabled, + mappingColors, + activeViewport, + mousePosition, + zoomStep, + position, + dataset, + segmentationLayer, + renderMissingDataBlack, + } = this.props; const cube = this.getSegmentationCube(); - const hasMapping = this.props.mapping != null; - const customColors = this.props.isMappingEnabled ? this.props.mappingColors : null; + const hasMapping = mapping != null; + const customColors = isMappingEnabled ? mappingColors : null; let globalMousePosition; - if (this.props.mousePosition && this.props.activeViewport !== OrthoViews.TDView) { - const [x, y] = this.props.mousePosition; + if (mousePosition && activeViewport !== OrthoViews.TDView) { + const [x, y] = mousePosition; globalMousePosition = calculateGlobalPos({ x, y }); } - const getIdForPos = pos => pos && cube.getDataValue(pos, null, this.props.zoomStep); + const flycamPosition = position; + const resolutions = getResolutions(dataset); + // While render missing data black is not active and there is no segmentation for the current zoom step, + // the segmentation of a higher zoom step is shown. Here we determine the the next zoom step of the + // displayed segmentation data to get the correct segment ids for the camera and the mouse position. + const getNextUsableZoomStepForPosition = pos => { + let usableZoomStep = zoomStep; + while ( + pos && + usableZoomStep < resolutions.length - 1 && + !cube.hasDataAtPositionAndZoomStep(pos, usableZoomStep) + ) { + usableZoomStep++; + } + return usableZoomStep; + }; + + const usableZoomStepForCameraPosition = renderMissingDataBlack + ? zoomStep + : getNextUsableZoomStepForPosition(flycamPosition); + const usableZoomStepForMousePosition = + renderMissingDataBlack || globalMousePosition == null + ? zoomStep + : getNextUsableZoomStepForPosition(globalMousePosition); + + const getResolutionOfZoomStepAsString = usedZoomStep => { + const usedResolution = segmentationLayer ? segmentationLayer.resolutions[usedZoomStep] : null; + return usedResolution + ? `${usedResolution[0]}-${usedResolution[1]}-${usedResolution[2]}` + : "Not available"; + }; + const getIdForPos = (pos, usableZoomStep) => + pos && cube.getDataValue(pos, null, usableZoomStep); const tableData = [ - { name: "Active ID", key: "active", unmapped: this.props.activeCellId }, { - name: "ID at current position", + name: "Active ID", + key: "active", + unmapped: this.props.activeCellId, + resolution: "", + }, + { + name: "ID at the center", key: "current", - unmapped: getIdForPos(this.props.position), + unmapped: getIdForPos(flycamPosition, usableZoomStepForCameraPosition), + resolution: getResolutionOfZoomStepAsString(usableZoomStepForCameraPosition), }, { name: ( @@ -160,7 +211,10 @@ class MappingInfoView extends React.Component { ), key: "mouse", - unmapped: getIdForPos(globalMousePosition), + unmapped: getIdForPos(globalMousePosition, usableZoomStepForMousePosition), + resolution: globalMousePosition + ? getResolutionOfZoomStepAsString(usableZoomStepForMousePosition) + : "Not available", }, ] .map(idInfo => ({ @@ -170,23 +224,40 @@ class MappingInfoView extends React.Component { .map(idInfo => ({ ...idInfo, unmapped: ( - {idInfo.unmapped} + + {idInfo.unmapped} + ), mapped: ( - + {idInfo.mapped} ), })); - const columnHelper = (title, dataIndex) => ({ title, dataIndex }); + const columnHelper = (title, dataIndex) => ({ + title, + dataIndex, + }); const idColumns = hasMapping && this.props.isMappingEnabled ? // Show an unmapped and mapped id column if there's a mapping [columnHelper("Unmapped", "unmapped"), columnHelper("Mapped", "mapped")] : // Otherwise, only show an ID column [columnHelper("ID", "unmapped")]; - const columns = [columnHelper("", "name"), ...idColumns]; + const columns = [ + columnHelper("", "name"), + ...idColumns, + columnHelper("Magnification", "resolution"), + ]; return ( tracing.activeCellId) .getOrElse(0), isMergerModeEnabled: state.temporaryConfiguration.isMergerModeEnabled, + renderMissingDataBlack: state.datasetConfiguration.renderMissingDataBlack, }; }