From c06043483d10029bda0e04f3dc3048de06c3b9e3 Mon Sep 17 00:00:00 2001 From: Bruno Alves de Faria Date: Fri, 30 Dec 2016 09:17:00 -0200 Subject: [PATCH] LT-115: Considering timepoint ID for measurement numbers --- .../client/components/viewer/viewer.js | 2 +- .../configuration/toolGroups/baseSchema.js | 23 +++ .../configuration/toolGroups/nonTargets.js | 18 +- .../both/configuration/toolGroups/targets.js | 18 +- .../both/configuration/toolGroups/temp.js | 18 +- .../measurementLocationDialog.js | 2 +- .../both/configuration/measurements.js | 178 +++--------------- .../components/caseProgress/caseProgress.js | 8 +- 8 files changed, 62 insertions(+), 205 deletions(-) create mode 100644 Packages/ohif-lesiontracker/both/configuration/toolGroups/baseSchema.js diff --git a/LesionTracker/client/components/viewer/viewer.js b/LesionTracker/client/components/viewer/viewer.js index a30241fc1..269e3ab15 100644 --- a/LesionTracker/client/components/viewer/viewer.js +++ b/LesionTracker/client/components/viewer/viewer.js @@ -101,7 +101,7 @@ Template.viewer.onCreated(() => { Session.set('TimepointsReady', true); const timepointIds = timepoints.map(t => t.timepointId); - instance.data.measurementApi = new OHIF.measurements.MeasurementApi(instance.data.currentTimepointId); + instance.data.measurementApi = new OHIF.measurements.MeasurementApi(instance.data.timepointApi); const measurementsPromise = instance.data.measurementApi.retrieveMeasurements(patientId, timepointIds); measurementsPromise.then(() => { Session.set('MeasurementsReady', true); diff --git a/Packages/ohif-lesiontracker/both/configuration/toolGroups/baseSchema.js b/Packages/ohif-lesiontracker/both/configuration/toolGroups/baseSchema.js new file mode 100644 index 000000000..05431563f --- /dev/null +++ b/Packages/ohif-lesiontracker/both/configuration/toolGroups/baseSchema.js @@ -0,0 +1,23 @@ +import { SimpleSchema } from 'meteor/aldeed:simple-schema'; + +export const ToolGroupBaseSchema = new SimpleSchema({ + toolId: { + type: String, + label: 'Tool ID' + }, + toolItemId: { + type: String, + label: 'Tool Item ID' + }, + createdAt: { + type: Date + }, + studyInstanceUid: { + type: String, + label: 'Study Instance UID' + }, + timepointId: { + type: String, + label: 'Timepoint ID' + } +}); diff --git a/Packages/ohif-lesiontracker/both/configuration/toolGroups/nonTargets.js b/Packages/ohif-lesiontracker/both/configuration/toolGroups/nonTargets.js index 26a0da477..1eb0eaf2b 100644 --- a/Packages/ohif-lesiontracker/both/configuration/toolGroups/nonTargets.js +++ b/Packages/ohif-lesiontracker/both/configuration/toolGroups/nonTargets.js @@ -1,23 +1,9 @@ -import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import { ToolGroupBaseSchema } from './baseSchema'; import { nonTarget } from '../tools/nonTarget'; -const NonTargetSchema = new SimpleSchema({ - toolId: { - type: String, - label: 'Tool ID' - }, - toolItemId: { - type: String, - label: 'Tool Item ID' - }, - createdAt: { - type: Date - } -}); - export const nonTargets = { id: 'nonTargets', name: 'Non-Targets', childTools: [nonTarget], - schema: NonTargetSchema + schema: ToolGroupBaseSchema }; diff --git a/Packages/ohif-lesiontracker/both/configuration/toolGroups/targets.js b/Packages/ohif-lesiontracker/both/configuration/toolGroups/targets.js index bc1df0eb2..b0a6b3b0c 100644 --- a/Packages/ohif-lesiontracker/both/configuration/toolGroups/targets.js +++ b/Packages/ohif-lesiontracker/both/configuration/toolGroups/targets.js @@ -1,25 +1,11 @@ -import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import { ToolGroupBaseSchema } from './baseSchema'; import { bidirectional } from '../tools/bidirectional'; import { targetCR } from '../tools/targetCR'; import { targetUN } from '../tools/targetUN'; -const TargetSchema = new SimpleSchema({ - toolId: { - type: String, - label: 'Tool ID' - }, - toolItemId: { - type: String, - label: 'Tool Item ID' - }, - createdAt: { - type: Date - } -}); - export const targets = { id: 'targets', name: 'Targets', childTools: [bidirectional, targetCR, targetUN], - schema: TargetSchema + schema: ToolGroupBaseSchema }; diff --git a/Packages/ohif-lesiontracker/both/configuration/toolGroups/temp.js b/Packages/ohif-lesiontracker/both/configuration/toolGroups/temp.js index 377ae2ee3..ced350989 100644 --- a/Packages/ohif-lesiontracker/both/configuration/toolGroups/temp.js +++ b/Packages/ohif-lesiontracker/both/configuration/toolGroups/temp.js @@ -1,24 +1,10 @@ -import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import { ToolGroupBaseSchema } from './baseSchema'; import { length } from '../tools/length'; import { ellipse } from '../tools/ellipse'; -const TempSchema = new SimpleSchema({ - toolId: { - type: String, - label: 'Tool ID' - }, - toolItemId: { - type: String, - label: 'Tool Item ID' - }, - createdAt: { - type: Date - } -}); - export const temp = { id: 'temp', name: 'Temporary', childTools: [length, ellipse], - schema: TempSchema + schema: ToolGroupBaseSchema }; diff --git a/Packages/ohif-lesiontracker/client/components/measurementLocationDialog/measurementLocationDialog.js b/Packages/ohif-lesiontracker/client/components/measurementLocationDialog/measurementLocationDialog.js index b073d4e5f..7c414216a 100644 --- a/Packages/ohif-lesiontracker/client/components/measurementLocationDialog/measurementLocationDialog.js +++ b/Packages/ohif-lesiontracker/client/components/measurementLocationDialog/measurementLocationDialog.js @@ -70,7 +70,7 @@ Template.measurementLocationDialog.onCreated(() => { setMeasurementNumberCallback: getSetMeasurementNumberCallbackFunction(measurementTypeId, measurementApi, timepointApi), // TODO: Check the position for these, the Add Label button position seems very awkward getMeasurementLocationCallback: toggleLabel, - changeMeasurementLocationCallback: toggleLabel + changeMeasurementLocationCallback: toggleLabel, }; diff --git a/Packages/ohif-measurements/both/configuration/measurements.js b/Packages/ohif-measurements/both/configuration/measurements.js index 79ecd8759..0ec390b86 100644 --- a/Packages/ohif-measurements/both/configuration/measurements.js +++ b/Packages/ohif-measurements/both/configuration/measurements.js @@ -14,9 +14,9 @@ class MeasurementApi { return configuration; } - constructor(currentTimepointId) { - if (currentTimepointId) { - this.currentTimepointId = currentTimepointId; + constructor(timepointApi) { + if (timepointApi) { + this.timepointApi = timepointApi; } this.toolGroups = {}; @@ -35,14 +35,24 @@ class MeasurementApi { this.tools[tool.id] = collection; collection.find().observe({ - added(measurement) { + added: measurement => { groupCollection.insert({ toolId: tool.id, - toolItemUid: measurement._id, + toolItemId: measurement._id, + timepointId: measurement.timepointId, + studyInstanceUid: measurement.studyInstanceUid, createdAt: measurement.createdAt }); - const measurementCount = groupCollection.find().count(); + const timepoint = this.timepointApi.timepoints.findOne({ + timepointId: measurement.timepointId + }); + const measurementCount = groupCollection.find({ + studyInstanceUid: { + $in: timepoint.studyInstanceUids + } + }).count(); + collection.update(measurement._id, { $set: { measurementNumber: measurementCount @@ -50,13 +60,20 @@ class MeasurementApi { }); }, - removedAt(measurement, atIndex) { + removedAt: (measurement, atIndex) => { groupCollection.remove({ - toolItemUid: measurement._id + toolItemId: measurement._id + }); + + const timepoint = this.timepointApi.timepoints.findOne({ + timepointId: measurement.timepointId }); toolGroup.childTools.forEach(childTool => { this.tools[childTool.id].update({ + studyInstanceUid: { + $in: timepoint.studyInstanceUids + }, measurementNumber: { $gt: atIndex } @@ -100,7 +117,7 @@ class MeasurementApi { }); } - storeMeasurements(timepoints) { + storeMeasurements() { const storeFn = configuration.dataExchange.store; if (!_.isFunction(storeFn)) { return; @@ -117,6 +134,7 @@ class MeasurementApi { }); }); + const timepoints = this.timepointApi.all(); const timepointIds = timepoints.map(t => t.timepointId); const patientId = timepoints[0].patientId; const filter = { @@ -126,6 +144,7 @@ class MeasurementApi { } }; + OHIF.log.info('Saving Measurements for timepoints:', timepoints); storeFn(measurementData, filter).then(() => { OHIF.log.info('Measurement storage completed'); }); @@ -149,144 +168,20 @@ class MeasurementApi { }); } - // TODO: Create a better function to combine hasDataAtTimepoint and hasNoDataAtTimepoint - // because this doesn't seem very elegant... - hasDataAtTimepoint(collection, timepointId) { - // Retrieve all the data for this Measurement type (e.g. 'targets') - // which was recorded at baseline. - const dataAtTimepoint = collection.find({timepointId}); - - // Obtain a list of the Measurement Numbers from the - // measurements which have data at this timepoint - const numbers = dataAtTimepoint.map(m => m.measurementNumber); - - // Retrieve all the data for this Measurement type which - // match the Measurement Numbers obtained above - const filter = { - measurementNumber: { - $in: numbers - } - }; - - return collection.find(filter).fetch(); - } - - hasNoDataAtTimepoint(collection, timepointId) { - // Retrieve all the data for this Measurement type (e.g. 'targets') - // which was recorded at baseline. - const dataAtTimepoint = collection.find({timepointId}); - - // Obtain a list of the Measurement Numbers from the - // measurements which have data at this timepoint - const numbers = dataAtTimepoint.map(m => m.measurementNumber); - - // Retrieve all the data for this Measurement type which - // match the Measurement Numbers obtained above - const filter = { - measurementNumber: { - $nin: numbers - } - }; - - return collection.find(filter).fetch(); - } - sortMeasurements(baselineTimepointId) { const tools = configuration.measurementTools; - const hasDataAtTimepoint = this.hasDataAtTimepoint; - const hasNoDataAtTimepoint = this.hasNoDataAtTimepoint; const includedTools = tools.filter(tool => { return (tool.options && tool.options.caseProgress && tool.options.caseProgress.include); }); - let overallMeasurementNumber = 1; - let specificToolMeasurementNumber = 1; - - - const updateMeasurementNumber = (collection, toolType) => { - return data => { - const filter = { - measurementNumber: data.measurementNumber, - toolType - } - - collection.update(filter, { - $set: { - measurementNumber: specificToolMeasurementNumber - } - }); - - // Increment the overall measurement number - specificToolMeasurementNumber += 1; - }; - }; - - const updateMeasurementNumberOverall = (collection, toolType) => { - return data => { - const filter = { - measurementNumber: data.measurementNumber, - toolType - } - - collection.update(filter, { - $set: { - measurementNumberOverall: overallMeasurementNumber - } - }); - - // Increment the overall measurement number - overallMeasurementNumber += 1; - }; - }; - - const summarizeMeasurement = (groupObject, toolType) => { - return key => { - return { - measurementNumber: parseInt(key, 10), - entries: groupObject[key], - toolType - }; - }; - }; - - // First, update Measurement Number and the displayed Measurements + // Update Measurement the displayed Measurements includedTools.forEach(tool => { const collection = this.tools[tool.id]; - const toolType = tool.cornerstoneToolType; - const measurements = collection.find({toolType}).fetch(); - const groupObject = _.groupBy(measurements, m => m.measurementNumber); - const sortedByMeasurementNumber = Object.keys(groupObject).map(summarizeMeasurement(groupObject, toolType)); - sortedByMeasurementNumber.forEach(updateMeasurementNumber(collection, toolType)) - + const measurements = collection.find().fetch(); measurements.forEach(measurement => { OHIF.measurements.syncMeasurementAndToolData(measurement); }); - - // Reset specificToolMeasurementNumber - specificToolMeasurementNumber = 1; - }); - - // Next, handle the overall measurement number. - // First, handle data that has a measurement at baseline - includedTools.forEach(tool => { - const collection = this.tools[tool.id]; - const toolType = tool.cornerstoneToolType; - const measurements = hasDataAtTimepoint(collection, baselineTimepointId); - const groupObject = _.groupBy(measurements, m => m.measurementNumber); - const sortedByMeasurementNumber = Object.keys(groupObject).map(summarizeMeasurement(groupObject, toolType)); - sortedByMeasurementNumber.forEach(updateMeasurementNumberOverall(collection, toolType)) - }); - - // Next, handle New Measurements (i.e. no baseline data) - // Note that this cannot be combined with the loop above due to the incrementing of the overallMeasurementNumber - includedTools.forEach(tool => { - const collection = this.tools[tool.id]; - const toolType = tool.cornerstoneToolType; - const measurements = hasNoDataAtTimepoint(collection, baselineTimepointId); - const groupObject = _.groupBy(measurements, m => m.measurementNumber); - const sortedByMeasurementNumber = Object.keys(groupObject).map(summarizeMeasurement(groupObject, toolType)); - sortedByMeasurementNumber.forEach(updateMeasurementNumberOverall(collection, toolType)); }); } @@ -322,19 +217,6 @@ class MeasurementApi { } }); - // Update the measurement numbers for the remaining measurements - const updateFilter = _.clone(filter); - updateFilter.measurementNumber = { - $gt: measurementNumber - }; - collection.update(updateFilter, { - $inc: { - measurementNumber: -1 - } - }, { - multi: true - }); - // Synchronize the updated measurements with Cornerstone Tools // toolData to make sure the displayed measurements show 'Target X' correctly const syncFilter = _.clone(updateFilter); diff --git a/Packages/ohif-measurements/client/components/caseProgress/caseProgress.js b/Packages/ohif-measurements/client/components/caseProgress/caseProgress.js index b8ef8e05b..fb7944043 100644 --- a/Packages/ohif-measurements/client/components/caseProgress/caseProgress.js +++ b/Packages/ohif-measurements/client/components/caseProgress/caseProgress.js @@ -11,16 +11,10 @@ Template.caseProgress.onCreated(() => { instance.isLocked = new ReactiveVar(); instance.saveData = () => { - - const timepointApi = instance.data.timepointApi; - const timepoints = timepointApi.all(); - OHIF.log.info('Saving Measurements for timepoints:'); - OHIF.log.info(timepoints); - instance.data.measurementApi.storeMeasurements(timepoints); + instance.data.measurementApi.storeMeasurements(); // Clear signaled unsaved changes... OHIF.ui.unsavedChanges.clear('viewer.studyViewer.measurements.*'); - }; instance.unsavedChangesHandler = () => {