diff --git a/Packages-react/ohif-viewer/src/App.js b/Packages-react/ohif-viewer/src/App.js index d865c7e61..1a85d7cc8 100644 --- a/Packages-react/ohif-viewer/src/App.js +++ b/Packages-react/ohif-viewer/src/App.js @@ -18,7 +18,6 @@ import { createUserManager, reducer as oidcReducer } from 'redux-oidc'; -import timepointManager from './redux/timepointManager'; import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'; const { ExtensionManager } = OHIF.extensions; @@ -28,7 +27,6 @@ const Icons = 'icons.svg'; const { reducers, localStorage } = OHIF.redux; reducers.ui = ui; reducers.oidc = oidcReducer; -reducers.timepointManager = timepointManager; const combined = combineReducers(reducers); const store = createStore(combined, localStorage.loadState()); diff --git a/Packages-react/ohif-viewer/src/connectedComponents/ConnectedMeasurementTable.js b/Packages-react/ohif-viewer/src/connectedComponents/ConnectedMeasurementTable.js index 1e850c69a..c1ee619dd 100644 --- a/Packages-react/ohif-viewer/src/connectedComponents/ConnectedMeasurementTable.js +++ b/Packages-react/ohif-viewer/src/connectedComponents/ConnectedMeasurementTable.js @@ -1,7 +1,100 @@ import { connect } from 'react-redux'; import { MeasurementTable } from 'react-viewerbase'; +import OHIF from 'ohif-core'; import moment from 'moment'; +function groupBy(list, props) { + return list.reduce((a, b) => { + (a[b[props]] = a[b[props]] || []).push(b); + return a; + }, {}); +} + +function getAllTools() { + const config = OHIF.measurements.MeasurementApi.getConfiguration(); + let tools = []; + config.measurementTools.forEach( toolGroup => + tools = tools.concat(toolGroup.childTools) + ); + + return tools; +} + +function getMeasurementText(measurementData) { + const { location, description} = measurementData; + let text = '...'; + if (location) { + text = location; + if (description) { + text += `(${description})`; + } + } + return text; +} + +function getDataForEachMeasurementNumber(measurementNumberList, timepoints, displayFunction) { + const data = []; + // on each measurement number we should get each measurement data by available timepoint + measurementNumberList.forEach( measurement => { + timepoints.forEach( timepoint => { + const eachData = { + displayText: '...' + } + if (measurement.timepointId === timepoint.timepointId) { + eachData.displayText = displayFunction(measurement); + } + data.push(eachData); + }); + }); + + return data; +} + +function convertMeasurementsToTableData(toolCollections, timepoints) { + const config = OHIF.measurements.MeasurementApi.getConfiguration(); + const toolGroups = config.measurementTools; + const tools = getAllTools(); + + const tableMeasurements = toolGroups.map( toolGroup => { + return { + groupName: toolGroup.name, + groupId: toolGroup.id, + measurements: [] + } + }); + + Object.keys(toolCollections).forEach(toolId => { + const toolMeasurements = toolCollections[toolId]; + const tool = tools.find(tool => tool.id === toolId); + const { displayFunction } = tool.options.measurementTable; + + // Group by measurementNumber so we can display then all in the same line + const groupedMeasurements = groupBy(toolMeasurements, 'measurementNumber'); + + Object.keys(groupedMeasurements).forEach( groupedMeasurementsIndex => { + const measurementNumberList = groupedMeasurements[groupedMeasurementsIndex]; + //check if all measurements with same measurementNumber will have same LABEL + const tableMeasurement = { + label: getMeasurementText(measurementNumberList[0]), + hasWarnings: false, //TODO + warningTitle: '', //TODO + isSplitLesion: false, //TODO + warningList: [], //TODO + data: getDataForEachMeasurementNumber(measurementNumberList, timepoints, displayFunction) + }; + + // find the group object for the tool + const toolGroupMeasurements = tableMeasurements.find( group => { + return group.groupId === tool.toolGroup; + }); + // inject the new measurement for this measurementNumer + toolGroupMeasurements.measurements.push(tableMeasurement); + }); + }); + + return tableMeasurements; +} + function convertTimepointsToTableData(timepoints) { if (!timepoints || !timepoints.length) { return []; @@ -15,41 +108,11 @@ function convertTimepointsToTableData(timepoints) { ]; } -function convertMeasurementsToTableData(measurements) { - const tableData = [ - { - groupName: 'Measurements', - measurements: [], - measurements1: measurements - } - ]; - - if (measurements && measurements.allTools) { - measurements.allTools.forEach(measurement => { - const tableMeasurement = { - label: '...', - hasWarnings: false, - warningTitle: '', - isSplitLesion: false, - warningList: [], - data: [ - { - displayText: '...' - } - ] - }; - tableData[0].measurements.push(tableMeasurement); - }); - } - - return tableData; -} - const mapStateToProps = state => { const { timepoints, measurements } = state.timepointManager; return { timepoints: convertTimepointsToTableData(timepoints), - measurementCollection: convertMeasurementsToTableData(measurements) + measurementCollection: convertMeasurementsToTableData(measurements, timepoints) }; }; diff --git a/Packages-react/ohif-viewer/src/connectedComponents/ConnectedViewer.js b/Packages-react/ohif-viewer/src/connectedComponents/ConnectedViewer.js index aeee34b36..8dffc1c9f 100644 --- a/Packages-react/ohif-viewer/src/connectedComponents/ConnectedViewer.js +++ b/Packages-react/ohif-viewer/src/connectedComponents/ConnectedViewer.js @@ -1,14 +1,16 @@ import { connect } from 'react-redux'; import Viewer from './Viewer.js'; -import actions from '../redux/actions.js'; +import OHIF from 'ohif-core'; + +const { setTimepoints, setMeasurements } = OHIF.redux.actions; const mapDispatchToProps = dispatch => { return { onTimepointsUpdated: timepoints => { - dispatch(actions.setTimepoints(timepoints)); + dispatch(setTimepoints(timepoints)); }, onMeasurementsUpdated: measurements => { - dispatch(actions.setMeasurements(measurements)); + dispatch(setMeasurements(measurements)); } }; }; diff --git a/Packages-react/ohif-viewer/src/connectedComponents/Viewer.js b/Packages-react/ohif-viewer/src/connectedComponents/Viewer.js index cc0dff989..76ee40075 100644 --- a/Packages-react/ohif-viewer/src/connectedComponents/Viewer.js +++ b/Packages-react/ohif-viewer/src/connectedComponents/Viewer.js @@ -9,7 +9,6 @@ import WhiteLabellingContext from '../WhiteLabellingContext.js'; import ConnectedHeader from './ConnectedHeader.js'; import ConnectedFlexboxLayout from './ConnectedFlexboxLayout.js'; import ConnectedToolbarRow from './ConnectedToolbarRow.js'; -import measurementTools from '../measurementTools'; import './Viewer.css'; /** * Inits OHIF Hanging Protocol's onReady. @@ -57,9 +56,7 @@ class Viewer extends Component { constructor(props) { super(props); - OHIF.measurements.MeasurementApi.setConfiguration({ - measurementTools, dataExchange: { retrieve: this.retrieveMeasurements, store: this.storeMeasurements @@ -169,10 +166,7 @@ class Viewer extends Component { const patientId = studies[0] && studies[0].patientId; timepointApi.retrieveTimepoints({ patientId }); - - // TODO: Retrieve measurements and sync them with tool data measurementApi.retrieveMeasurements(patientId, [currentTimepointId]); - //measurementApi.syncMeasurementsAndToolData(); } render() { diff --git a/Packages-react/ohif-viewer/src/measurementTools/ArrowAnnotate.js b/Packages-react/ohif-viewer/src/measurementTools/ArrowAnnotate.js deleted file mode 100644 index 9446bd780..000000000 --- a/Packages-react/ohif-viewer/src/measurementTools/ArrowAnnotate.js +++ /dev/null @@ -1,15 +0,0 @@ -const displayFunction = data => { - return data.text || ''; -}; - -export default { - id: 'ArrowAnnotate', - name: 'ArrowAnnotate', - toolGroup: 'allTools', - cornerstoneToolType: 'ArrowAnnotate', - options: { - measurementTable: { - displayFunction - } - } -}; diff --git a/Packages-react/ohif-viewer/src/measurementTools/EllipticalRoi.js b/Packages-react/ohif-viewer/src/measurementTools/EllipticalRoi.js deleted file mode 100644 index 2747a0a81..000000000 --- a/Packages-react/ohif-viewer/src/measurementTools/EllipticalRoi.js +++ /dev/null @@ -1,22 +0,0 @@ -const displayFunction = data => { - let meanValue = ''; - if (data.meanStdDev && data.meanStdDev.mean) { - meanValue = data.meanStdDev.mean.toFixed(2) + ' HU'; - } - return meanValue; - // let meanValue = data.meanStdDev && data.meanStdDev.mean || 0; - // return numberWithCommas(meanValue).toFixed(2) + ' HU'; - //return data.meanStdDev.mean.toFixed(2); -}; - -export default { - id: 'EllipticalRoi', - name: 'Ellipse', - toolGroup: 'allTools', - cornerstoneToolType: 'EllipticalRoi', - options: { - measurementTable: { - displayFunction - } - } -}; diff --git a/Packages-react/ohif-viewer/src/measurementTools/Length.js b/Packages-react/ohif-viewer/src/measurementTools/Length.js deleted file mode 100644 index d02687881..000000000 --- a/Packages-react/ohif-viewer/src/measurementTools/Length.js +++ /dev/null @@ -1,19 +0,0 @@ -const displayFunction = data => { - let lengthValue = ''; - if (data.length) { - lengthValue = data.length.toFixed(2) + ' mm'; - } - return lengthValue; -}; - -export default { - id: 'Length', - name: 'Length', - toolGroup: 'allTools', - cornerstoneToolType: 'Length', - options: { - measurementTable: { - displayFunction - } - } -}; diff --git a/Packages-react/ohif-viewer/src/measurementTools/SimpleAngle.js b/Packages-react/ohif-viewer/src/measurementTools/SimpleAngle.js deleted file mode 100644 index 0792325fd..000000000 --- a/Packages-react/ohif-viewer/src/measurementTools/SimpleAngle.js +++ /dev/null @@ -1,19 +0,0 @@ -const displayFunction = data => { - let text = ''; - if (data.rAngle) { - text = data.rAngle.toFixed(2) + String.fromCharCode(parseInt('00B0', 16)); - } - return text; -}; - -export default { - id: 'SimpleAngle', - name: 'SimpleAngle', - toolGroup: 'allTools', - cornerstoneToolType: 'SimpleAngle', - options: { - measurementTable: { - displayFunction - } - } -}; diff --git a/Packages-react/ohif-viewer/src/measurementTools/index.js b/Packages-react/ohif-viewer/src/measurementTools/index.js deleted file mode 100644 index e6e1ec548..000000000 --- a/Packages-react/ohif-viewer/src/measurementTools/index.js +++ /dev/null @@ -1,21 +0,0 @@ -import Length from './Length'; -import EllipticalRoi from './EllipticalRoi'; -import RectangleRoi from './rectangleRoi'; -import SimpleAngle from './SimpleAngle'; -import ArrowAnnotate from './ArrowAnnotate'; - -const trackedTools = [ - Length, - EllipticalRoi, - RectangleRoi, - SimpleAngle, - ArrowAnnotate -]; - -export default [ - { - id: 'allTools', - name: 'Measurements', - childTools: trackedTools - } -]; diff --git a/Packages-react/ohif-viewer/src/measurementTools/rectangleRoi.js b/Packages-react/ohif-viewer/src/measurementTools/rectangleRoi.js deleted file mode 100644 index 893e0c4a9..000000000 --- a/Packages-react/ohif-viewer/src/measurementTools/rectangleRoi.js +++ /dev/null @@ -1,19 +0,0 @@ -const displayFunction = data => { - let meanValue = ''; - if (data.meanStdDev && data.meanStdDev.mean) { - meanValue = data.meanStdDev.mean.toFixed(2) + ' HU'; - } - return meanValue; -}; - -export default { - id: 'RectangleRoi', - name: 'Rectangle', - toolGroup: 'allTools', - cornerstoneToolType: 'RectangleRoi', - options: { - measurementTable: { - displayFunction - } - } -}; diff --git a/Packages-react/ohif-viewer/src/redux/actions.js b/Packages-react/ohif-viewer/src/redux/actions.js index 7e7971a4b..cd031e9d6 100644 --- a/Packages-react/ohif-viewer/src/redux/actions.js +++ b/Packages-react/ohif-viewer/src/redux/actions.js @@ -13,22 +13,10 @@ export const setUserPreferencesModalOpen = state => ({ state }); -export const setTimepoints = state => ({ - type: 'SET_TIMEPOINTS', - state -}); - -export const setMeasurements = state => ({ - type: 'SET_MEASUREMENTS', - state -}); - const actions = { setLeftSidebarOpen, setRightSidebarOpen, setUserPreferencesModalOpen, - setTimepoints, - setMeasurements }; export default actions; diff --git a/Packages-react/ohif-viewer/src/redux/timepointManager.js b/Packages-react/ohif-viewer/src/redux/timepointManager.js deleted file mode 100644 index a1d9605c0..000000000 --- a/Packages-react/ohif-viewer/src/redux/timepointManager.js +++ /dev/null @@ -1,17 +0,0 @@ -const defaultState = { - timepoints: [], - measurements: [] -}; - -const timepointManager = (state = defaultState, action) => { - switch (action.type) { - case 'SET_TIMEPOINTS': - return Object.assign({}, state, { timepoints: action.state }); - case 'SET_MEASUREMENTS': - return Object.assign({}, state, { measurements: action.state }); - default: - return state; - } -}; - -export default timepointManager;