From 065a81d6e748826c13fc697889adc4c6b43af361 Mon Sep 17 00:00:00 2001 From: Evren Ozkan Date: Mon, 13 May 2019 18:07:57 -0400 Subject: [PATCH] fix(measurements): Show missing measurements in measurement table (#426) - Bump cornerstone-tools to 3.9.0, ohif-core to 0.5.2 and react-viewerbase to 0.4.1 - Add bidirectional, elliptical, circle and rectangle roi tools - Support labeling and context-menu for all annotation tools - Sort measurements by lesion naming number to show the last added measurement in the end in measurement table --- package.json | 6 +-- .../ConnectedMeasurementTable.js | 36 +++++++++------ src/connectedComponents/ToolContextMenu.js | 10 +++- src/setupTools.js | 46 ++++++++++++++++++- src/utils/getDefaultToolbarButtons.js | 28 +++++++++++ yarn.lock | 24 +++++----- 6 files changed, 119 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 7ad8a672d..cc94fb3f4 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "classnames": "^2.2.6", "cornerstone-core": "^2.2.8", "cornerstone-math": "^0.1.8", - "cornerstone-tools": "^3.2.4", + "cornerstone-tools": "^3.9.0", "cornerstone-wado-image-loader": "^2.2.3", "dcmjs": "^0.3.8", "dicom-parser": "^1.8.3", @@ -76,7 +76,7 @@ "hammerjs": "^2.0.8", "lodash.isequal": "4.5.0", "moment": "^2.24.0", - "ohif-core": "0.4.2", + "ohif-core": "0.5.2", "ohif-cornerstone-extension": "^0.0.28", "ohif-dicom-html-extension": "^0.0.2", "ohif-dicom-microscopy-extension": "^0.0.5", @@ -91,7 +91,7 @@ "react-resize-detector": "^3.4.0", "react-router": "^4.3.1", "react-router-dom": "^4.3.1", - "react-viewerbase": "0.3.2", + "react-viewerbase": "0.4.1", "react-vtkjs-viewport": "^0.0.7", "redux": "^4.0.1", "redux-oidc": "3.1.x" diff --git a/src/connectedComponents/ConnectedMeasurementTable.js b/src/connectedComponents/ConnectedMeasurementTable.js index c474f601a..c18b0858f 100644 --- a/src/connectedComponents/ConnectedMeasurementTable.js +++ b/src/connectedComponents/ConnectedMeasurementTable.js @@ -6,12 +6,12 @@ import cornerstone from 'cornerstone-core' import jumpToRowItem from '../lib/jumpToRowItem.js' import getMeasurementLocationCallback from '../lib/getMeasurementLocationCallback' -const { setViewportSpecificData } = OHIF.redux.actions; +const { setViewportSpecificData } = OHIF.redux.actions const { MeasurementApi } = OHIF.measurements function groupBy(list, props) { return list.reduce((a, b) => { - (a[b[props]] = a[b[props]] || []).push(b) + ;(a[b[props]] = a[b[props]] || []).push(b) return a }, {}) } @@ -84,17 +84,18 @@ function convertMeasurementsToTableData(toolCollections, timepoints) { Object.keys(groupedMeasurements).forEach(groupedMeasurementsIndex => { const measurementNumberList = groupedMeasurements[groupedMeasurementsIndex] - + const measurementData = measurementNumberList[0] const { measurementNumber, lesionNamingNumber, toolType, - } = measurementNumberList[0] - const measurementId = measurementNumberList[0]._id + } = measurementData + const measurementId = measurementData._id //check if all measurements with same measurementNumber will have same LABEL const tableMeasurement = { - label: getMeasurementText(measurementNumberList[0]), + itemNumber: lesionNamingNumber, + label: getMeasurementText(measurementData), measurementId, measurementNumber, lesionNamingNumber, @@ -119,6 +120,13 @@ function convertMeasurementsToTableData(toolCollections, timepoints) { }) }) + // Sort measurements by lesion naming number + tableMeasurements.forEach(tm => { + tm.measurements.sort((m1, m2) => + m1.lesionNamingNumber > m2.lesionNamingNumber ? 1 : -1 + ) + }) + return tableMeasurements } @@ -230,9 +238,9 @@ const mapDispatchToProps = dispatch => { ) actionData.viewportSpecificData.forEach(viewportSpecificData => { - const { viewportIndex, displaySet } = viewportSpecificData; + const { viewportIndex, displaySet } = viewportSpecificData - dispatch(setViewportSpecificData(viewportIndex, displaySet)); + dispatch(setViewportSpecificData(viewportIndex, displaySet)) }) const { toolType, measurementNumber } = measurementData @@ -320,7 +328,7 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => { ) }, onDeleteClick: (event, measurementData) => { - const { MeasurementHandlers } = OHIF.measurements; + const { MeasurementHandlers } = OHIF.measurements MeasurementHandlers.onRemoved({ detail: { @@ -328,11 +336,11 @@ const mergeProps = (propsFromState, propsFromDispatch, ownProps) => { measurementData: { _id: measurementData.measurementId, lesionNamingNumber: measurementData.lesionNamingNumber, - measurementNumber: measurementData.measurementNumber - } - } - }); - } + measurementNumber: measurementData.measurementNumber, + }, + }, + }) + }, } } diff --git a/src/connectedComponents/ToolContextMenu.js b/src/connectedComponents/ToolContextMenu.js index b37902d39..923f303ee 100644 --- a/src/connectedComponents/ToolContextMenu.js +++ b/src/connectedComponents/ToolContextMenu.js @@ -6,7 +6,15 @@ import getMeasurementLocationCallback from '../lib/getMeasurementLocationCallbac import './ToolContextMenu.css' -const toolTypes = ['Angle', 'Length'] +const toolTypes = [ + 'Angle', + 'Bidirectional', + 'Length', + 'FreehandMouse', + 'EllipticalRoi', + 'CircleRoi', + 'RectangleRoi', +] let defaultDropdownItems = [ { diff --git a/src/setupTools.js b/src/setupTools.js index 8133780dc..6852d83c4 100644 --- a/src/setupTools.js +++ b/src/setupTools.js @@ -145,6 +145,15 @@ export default function setupTools(store) { { name: 'Pan', mouseButtonMasks: [1, 4] }, { name: 'Zoom', mouseButtonMasks: [1, 2] }, { name: 'Wwwc', mouseButtonMasks: [1] }, + { + name: 'Bidirectional', + configuration: { + configuration: { + getMeasurementLocationCallback: toolLabellingFlowCallback, + }, + }, + mouseButtonMasks: [1], + }, { name: 'Length', configuration: { @@ -165,7 +174,42 @@ export default function setupTools(store) { }, { name: 'StackScroll', mouseButtonMasks: [1] }, { name: 'Brush', mouseButtonMasks: [1] }, - { name: 'FreehandMouse', mouseButtonMasks: [1] }, + { + name: 'FreehandMouse', + configuration: { + configuration: { + getMeasurementLocationCallback: toolLabellingFlowCallback, + }, + }, + mouseButtonMasks: [1], + }, + { + name: 'EllipticalRoi', + configuration: { + configuration: { + getMeasurementLocationCallback: toolLabellingFlowCallback, + }, + }, + mouseButtonMasks: [1], + }, + { + name: 'CircleRoi', + configuration: { + configuration: { + getMeasurementLocationCallback: toolLabellingFlowCallback, + }, + }, + mouseButtonMasks: [1], + }, + { + name: 'RectangleRoi', + configuration: { + configuration: { + getMeasurementLocationCallback: toolLabellingFlowCallback, + }, + }, + mouseButtonMasks: [1], + }, { name: 'PanMultiTouch' }, { name: 'ZoomTouchPinch' }, { name: 'StackScrollMouseWheel' }, diff --git a/src/utils/getDefaultToolbarButtons.js b/src/utils/getDefaultToolbarButtons.js index 84ff9e958..93ca8bd15 100644 --- a/src/utils/getDefaultToolbarButtons.js +++ b/src/utils/getDefaultToolbarButtons.js @@ -60,6 +60,13 @@ export default function(baseDirectory = '/') { iconClasses: 'fa fa-angle-left', active: false, }, + { + command: 'Bidirectional', + type: 'tool', + text: 'Bidirectional', + svgUrl: `${relativePathToIcons}#icon-tools-measure-target`, + active: false, + }, { command: 'Brush', type: 'tool', @@ -74,6 +81,27 @@ export default function(baseDirectory = '/') { iconClasses: 'fa fa-star', active: false, }, + { + command: 'EllipticalRoi', + type: 'tool', + text: 'EllipticalRoi', + iconClasses: 'far fa-circle', + active: false, + }, + { + command: 'CircleRoi', + type: 'tool', + text: 'CircleRoi', + iconClasses: 'far fa-dot-circle', + active: false, + }, + { + command: 'RectangleRoi', + type: 'tool', + text: 'RectangleRoi', + iconClasses: 'far fa-square', + active: false, + }, { command: 'reset', type: 'command', diff --git a/yarn.lock b/yarn.lock index 5df38551e..2beb85360 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3465,10 +3465,10 @@ cornerstone-math@^0.1.8: resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.8.tgz#68ab1f9e4fdcd7c5cb23a0d2eb4263f9f894f1c5" integrity sha512-x7NEQHBtVG7j1yeyj/aRoKTpXv1Vh2/H9zNLMyqYJDtJkNng8C4Q8M3CgZ1qer0Yr7eVq2x+Ynmj6kfOm5jXKw== -cornerstone-tools@^3.2.4: - version "3.7.0" - resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-3.7.0.tgz#203c126843537cb73b97324f47d02fec6e575db8" - integrity sha512-dVlkKf1jDq/ShiJR5zs2kp44tERioXByVe+ZCvc6zVkltnDAFYqObPvuu3XHbO8rsFra/PM3xvTYF1rW+si4Lg== +cornerstone-tools@^3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-3.9.0.tgz#6e5a2865fe2ba6d80bf907b1b9734848b83132a0" + integrity sha512-gi+KhxYx3OEr4E0vt7Rp+MiQ5SRf1Qf/qf/D12i/VywDg3mPTLpe588nZZoUxeBJc0wF2s+Zybyv15NrbkoP2Q== dependencies: "@babel/runtime" "7.1.2" cornerstone-math "0.1.7" @@ -9603,10 +9603,10 @@ octokit-pagination-methods@^1.1.0: resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== -ohif-core@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.4.2.tgz#1ed2db0cddbd9ac15d5c97b9c789793d791be258" - integrity sha512-Wddeta9hKZDe1yyPp2QgtxhL0nM3vSudq52gRXcIVmtl0xCHzRrWqPqCTX10R3BU8OUXsHEF66RQ2gSVJmjH7g== +ohif-core@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/ohif-core/-/ohif-core-0.5.2.tgz#104a68824d35c5399d4da87ca6adb1de9bdd39ae" + integrity sha512-2Mt1b5iOgAGgP3TpGZfgoeR5AhF84XLaTEIz83TfQ4tCdRfXhSM1nMUk5bRzYpKAppZqTpYSdOlKChmqIaMwCg== dependencies: "@babel/runtime" "^7.2.0" ajv "^6.10.0" @@ -11681,10 +11681,10 @@ react-transition-group@^2.0.0, react-transition-group@^2.2.0: prop-types "^15.6.2" react-lifecycles-compat "^3.0.4" -react-viewerbase@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.3.2.tgz#03908eac75a325c1dca5c7fb7755e21119f7145a" - integrity sha512-o1xM7kWgsnaXuvaZt8BeA+NJjIZvU9HWA12m5pvNfCB4a1YfKIyYXNtaP39MbuA7sIS3vHDaBU3IKHL/uFPd2w== +react-viewerbase@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.4.1.tgz#82a381f25d1c00ea4efd5fed460748aee4ee7706" + integrity sha512-UG5yR515JG7natLavMa61X58xX/LBVaPQraQWFBvO2DfB2LzvFI8B8S+N7BVWZY8aGKlSHhwQWK9fHzO/GceMw== dependencies: "@babel/runtime" "7.2.0" classnames "2.2.6"