LT-115: Adapting MeasurementAPI to new tools storage structure

This commit is contained in:
Bruno Alves de Faria 2016-12-28 18:18:56 -02:00
parent bd748eae32
commit c9c2cd548e
14 changed files with 77 additions and 72 deletions

View File

@ -1,5 +1,6 @@
import { Template } from 'meteor/templating'; import { Template } from 'meteor/templating';
import { Session } from 'meteor/session'; import { Session } from 'meteor/session';
import { ReactiveDict } from 'meteor/reactive-dict';
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
import { _ } from 'meteor/underscore'; import { _ } from 'meteor/underscore';
@ -132,8 +133,6 @@ Template.viewer.onCreated(() => {
return; return;
} }
// Find and activate the first measurement by Lesion Number // Find and activate the first measurement by Lesion Number
// NOTE: This is inefficient, we should be using a hanging protocol // NOTE: This is inefficient, we should be using a hanging protocol
// to hang the first measurement's imageId immediately, rather // to hang the first measurement's imageId immediately, rather
@ -143,7 +142,7 @@ Template.viewer.onCreated(() => {
const measurementApi = instance.data.measurementApi; const measurementApi = instance.data.measurementApi;
const timepointApi = instance.data.timepointApi; const timepointApi = instance.data.timepointApi;
const collection = measurementApi[measurementTypeId]; const collection = measurementApi.tools[measurementTypeId];
const sorting = { const sorting = {
sort: { sort: {
measurementNumber: -1 measurementNumber: -1
@ -155,7 +154,7 @@ Template.viewer.onCreated(() => {
const current = timepointApi.current(); const current = timepointApi.current();
if (!current) { if (!current) {
return; return;
}; }
let timepoints = [current]; let timepoints = [current];
const prior = timepointApi.prior(); const prior = timepointApi.prior();
@ -181,14 +180,14 @@ Template.viewer.onCreated(() => {
} }
firstMeasurementActivated = true; firstMeasurementActivated = true;
}) });
}); });
Template.viewer.helpers({ Template.viewer.helpers({
dataSourcesReady() { dataSourcesReady() {
// TODO: Find a better way to do this // TODO: Find a better way to do this
const ready = Session.get('TimepointsReady') && Session.get('MeasurementsReady'); const ready = Session.get('TimepointsReady') && Session.get('MeasurementsReady');
console.log('dataSourcesReady? : ' + ready); OHIF.log.info('dataSourcesReady? : ' + ready);
return ready; return ready;
} }
}); });
@ -197,9 +196,11 @@ Template.viewer.events({
'CornerstoneToolsMeasurementAdded .imageViewerViewport'(event, instance, eventData) { 'CornerstoneToolsMeasurementAdded .imageViewerViewport'(event, instance, eventData) {
OHIF.measurements.MeasurementHandlers.onAdded(event, instance, eventData); OHIF.measurements.MeasurementHandlers.onAdded(event, instance, eventData);
}, },
'CornerstoneToolsMeasurementModified .imageViewerViewport'(event, instance, eventData) { 'CornerstoneToolsMeasurementModified .imageViewerViewport'(event, instance, eventData) {
OHIF.measurements.MeasurementHandlers.onModified(event, instance, eventData); OHIF.measurements.MeasurementHandlers.onModified(event, instance, eventData);
}, },
'CornerstoneToolsMeasurementRemoved .imageViewerViewport'(event, instance, eventData) { 'CornerstoneToolsMeasurementRemoved .imageViewerViewport'(event, instance, eventData) {
OHIF.measurements.MeasurementHandlers.onRemoved(event, instance, eventData); OHIF.measurements.MeasurementHandlers.onRemoved(event, instance, eventData);
} }

View File

@ -1,8 +1,3 @@
import { target } from './target';
import { nonTarget } from './nonTarget';
import { length } from './length';
import { ellipse } from './ellipse';
export const validateMeasurements = () => { export const validateMeasurements = () => {
console.log('validateMeasurements'); console.log('validateMeasurements');
}; };

View File

@ -1,6 +1,3 @@
import './nonTarget.js';
import './ellipse.js';
import './length.js';
import './measurementTools.js'; import './measurementTools.js';
import './dataExchange.js'; import './dataExchange.js';
import './dataValidation.js'; import './dataValidation.js';

View File

@ -86,6 +86,8 @@ const displayFunction = data => {
}; };
export const bidirectional = { export const bidirectional = {
id: 'bidirectional',
name: 'Target',
toolGroup: 'targets', toolGroup: 'targets',
cornerstoneToolType: 'bidirectional', cornerstoneToolType: 'bidirectional',
schema: BidirectionalSchema, schema: BidirectionalSchema,

View File

@ -4,18 +4,18 @@ import { MeasurementSchemaTypes } from 'meteor/ohif:measurements/both/schema/mea
const CornerstoneHandleSchema = MeasurementSchemaTypes.CornerstoneHandleSchema; const CornerstoneHandleSchema = MeasurementSchemaTypes.CornerstoneHandleSchema;
const EllipseHandlesSchema = new SimpleSchema({ const EllipseHandlesSchema = new SimpleSchema({
start: { start: {
type: CornerstoneHandleSchema, type: CornerstoneHandleSchema,
label: 'Start' label: 'Start'
}, },
end: { end: {
type: CornerstoneHandleSchema, type: CornerstoneHandleSchema,
label: 'End' label: 'End'
}, },
textBox: { textBox: {
type: CornerstoneHandleSchema, type: CornerstoneHandleSchema,
label: 'Text Box' label: 'Text Box'
}, },
}); });
const EllipseSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMeasurement, { const EllipseSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMeasurement, {
@ -28,6 +28,7 @@ const EllipseSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMe
export const ellipse = { export const ellipse = {
id: 'ellipse', id: 'ellipse',
name: 'Ellipse', name: 'Ellipse',
toolGroup: 'temp',
cornerstoneToolType: 'ellipticalRoi', cornerstoneToolType: 'ellipticalRoi',
schema: EllipseSchema schema: EllipseSchema
} };

View File

@ -4,18 +4,18 @@ import { MeasurementSchemaTypes } from 'meteor/ohif:measurements/both/schema/mea
const CornerstoneHandleSchema = MeasurementSchemaTypes.CornerstoneHandleSchema; const CornerstoneHandleSchema = MeasurementSchemaTypes.CornerstoneHandleSchema;
const LengthHandlesSchema = new SimpleSchema({ const LengthHandlesSchema = new SimpleSchema({
start: { start: {
type: CornerstoneHandleSchema, type: CornerstoneHandleSchema,
label: 'Start' label: 'Start'
}, },
end: { end: {
type: CornerstoneHandleSchema, type: CornerstoneHandleSchema,
label: 'End' label: 'End'
}, },
textBox: { textBox: {
type: CornerstoneHandleSchema, type: CornerstoneHandleSchema,
label: 'Text Box' label: 'Text Box'
}, }
}); });
const LengthSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMeasurement, { const LengthSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMeasurement, {
@ -28,6 +28,7 @@ const LengthSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMea
export const length = { export const length = {
id: 'length', id: 'length',
name: 'Length', name: 'Length',
toolGroup: 'temp',
cornerstoneToolType: 'length', cornerstoneToolType: 'length',
schema: LengthSchema schema: LengthSchema
} };

View File

@ -45,6 +45,8 @@ const NonTargetSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneTool
}]); }]);
export const nonTarget = { export const nonTarget = {
id: 'nonTarget',
name: 'Non-Target',
toolGroup: 'nonTargets', toolGroup: 'nonTargets',
cornerstoneToolType: 'nonTarget', cornerstoneToolType: 'nonTarget',
schema: NonTargetSchema, schema: NonTargetSchema,

View File

@ -50,6 +50,8 @@ const TargetCRSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolM
}]); }]);
export const targetCR = { export const targetCR = {
id: 'targetCR',
name: 'CR Target',
toolGroup: 'targets', toolGroup: 'targets',
cornerstoneToolType: 'targetCR', cornerstoneToolType: 'targetCR',
schema: TargetCRSchema, schema: TargetCRSchema,

View File

@ -50,6 +50,8 @@ const TargetUNSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolM
}]); }]);
export const targetUN = { export const targetUN = {
id: 'targetUN',
name: 'UN Target',
toolGroup: 'targets', toolGroup: 'targets',
cornerstoneToolType: 'targetUN', cornerstoneToolType: 'targetUN',
schema: TargetUNSchema, schema: TargetUNSchema,

View File

@ -7,7 +7,7 @@ import { FieldLesionLocation, FieldLesionLocationResponse } from 'meteor/ohif:le
Template.dialogNonTargetMeasurement.onCreated(() => { Template.dialogNonTargetMeasurement.onCreated(() => {
const instance = Template.instance(); const instance = Template.instance();
instance.measurementTypeId = 'nonTargets'; instance.measurementTypeId = 'nonTarget';
const timepointApi = instance.data.timepointApi; const timepointApi = instance.data.timepointApi;
instance.schema = new SimpleSchema({ instance.schema = new SimpleSchema({
@ -63,7 +63,7 @@ Template.dialogNonTargetMeasurement.onRendered(() => {
const measurementApi = instance.viewerData.measurementApi; const measurementApi = instance.viewerData.measurementApi;
const timepointApi = instance.viewerData.timepointApi; const timepointApi = instance.viewerData.timepointApi;
const collection = measurementApi[instance.measurementTypeId]; const collection = measurementApi.tools[instance.measurementTypeId];
const measurementData = instance.data.measurementData; const measurementData = instance.data.measurementData;

View File

@ -24,7 +24,7 @@ function getSetMeasurementNumberCallbackFunction(measurementTypeId, measurementA
// Get a measurement number for this measurement, depending on whether or not the same measurement previously // Get a measurement number for this measurement, depending on whether or not the same measurement previously
// exists at a different timepoint // exists at a different timepoint
const timepointId = timepoint.timepointId; const timepointId = timepoint.timepointId;
const collection = measurementApi[measurementTypeId]; const collection = measurementApi.tools[measurementTypeId];
const measurementNumber = OHIF.measurements.MeasurementManager.getNewMeasurementNumber(timepointId, collection, timepointApi); const measurementNumber = OHIF.measurements.MeasurementManager.getNewMeasurementNumber(timepointId, collection, timepointApi);
measurementData.measurementNumber = measurementNumber; measurementData.measurementNumber = measurementNumber;
@ -35,7 +35,7 @@ function getSetMeasurementNumberCallbackFunction(measurementTypeId, measurementA
Template.measurementLocationDialog.onCreated(() => { Template.measurementLocationDialog.onCreated(() => {
const instance = Template.instance(); const instance = Template.instance();
const measurementTypeId = 'targets'; const measurementTypeId = 'bidirectional';
const measurementApi = instance.data.measurementApi; const measurementApi = instance.data.measurementApi;
const timepointApi = instance.data.timepointApi; const timepointApi = instance.data.timepointApi;

View File

@ -19,12 +19,21 @@ class MeasurementApi {
this.currentTimepointId = currentTimepointId; this.currentTimepointId = currentTimepointId;
} }
configuration.measurementTools.forEach(tool => { this.toolGroups = {};
const measurementTypeId = tool.id; this.tools = {};
this[measurementTypeId] = new Mongo.Collection(null); configuration.measurementTools.forEach(toolGroup => {
this[measurementTypeId]._debugName = tool.name; const collection = new Mongo.Collection(null);
this[measurementTypeId].attachSchema(tool.schema); collection._debugName = toolGroup.name;
collection.attachSchema(toolGroup.schema);
this.toolGroups[toolGroup.id] = collection;
toolGroup.childTools.forEach(tool => {
const collection = new Mongo.Collection(null);
collection._debugName = tool.name;
collection.attachSchema(tool.schema);
this.tools[tool.id] = collection;
});
}); });
} }
@ -45,7 +54,7 @@ class MeasurementApi {
measurements.forEach(measurement => { measurements.forEach(measurement => {
delete measurement._id; delete measurement._id;
this[measurementTypeId].insert(measurement); this.tools[measurementTypeId].insert(measurement);
}); });
}); });
@ -63,7 +72,7 @@ class MeasurementApi {
let measurementData = {}; let measurementData = {};
configuration.measurementTools.forEach(tool => { configuration.measurementTools.forEach(tool => {
const measurementTypeId = tool.id; const measurementTypeId = tool.id;
measurementData[measurementTypeId] = this[measurementTypeId].find().fetch(); measurementData[measurementTypeId] = this.tools[measurementTypeId].find().fetch();
}); });
const timepointIds = timepoints.map(t => t.timepointId); const timepointIds = timepoints.map(t => t.timepointId);
@ -89,7 +98,7 @@ class MeasurementApi {
syncMeasurementsAndToolData() { syncMeasurementsAndToolData() {
configuration.measurementTools.forEach(tool => { configuration.measurementTools.forEach(tool => {
const measurements = this[tool.id].find().fetch(); const measurements = this.tools[tool.id].find().fetch();
measurements.forEach(measurement => { measurements.forEach(measurement => {
OHIF.measurements.syncMeasurementAndToolData(measurement); OHIF.measurements.syncMeasurementAndToolData(measurement);
}); });
@ -199,7 +208,7 @@ class MeasurementApi {
// First, update Measurement Number and the displayed Measurements // First, update Measurement Number and the displayed Measurements
includedTools.forEach(tool => { includedTools.forEach(tool => {
const collection = this[tool.id]; const collection = this.tools[tool.id];
const toolType = tool.cornerstoneToolType; const toolType = tool.cornerstoneToolType;
const measurements = collection.find({toolType}).fetch(); const measurements = collection.find({toolType}).fetch();
const groupObject = _.groupBy(measurements, m => m.measurementNumber); const groupObject = _.groupBy(measurements, m => m.measurementNumber);
@ -217,7 +226,7 @@ class MeasurementApi {
// Next, handle the overall measurement number. // Next, handle the overall measurement number.
// First, handle data that has a measurement at baseline // First, handle data that has a measurement at baseline
includedTools.forEach(tool => { includedTools.forEach(tool => {
const collection = this[tool.id]; const collection = this.tools[tool.id];
const toolType = tool.cornerstoneToolType; const toolType = tool.cornerstoneToolType;
const measurements = hasDataAtTimepoint(collection, baselineTimepointId); const measurements = hasDataAtTimepoint(collection, baselineTimepointId);
const groupObject = _.groupBy(measurements, m => m.measurementNumber); const groupObject = _.groupBy(measurements, m => m.measurementNumber);
@ -228,7 +237,7 @@ class MeasurementApi {
// Next, handle New Measurements (i.e. no baseline data) // 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 // Note that this cannot be combined with the loop above due to the incrementing of the overallMeasurementNumber
includedTools.forEach(tool => { includedTools.forEach(tool => {
const collection = this[tool.id]; const collection = this.tools[tool.id];
const toolType = tool.cornerstoneToolType; const toolType = tool.cornerstoneToolType;
const measurements = hasNoDataAtTimepoint(collection, baselineTimepointId); const measurements = hasNoDataAtTimepoint(collection, baselineTimepointId);
const groupObject = _.groupBy(measurements, m => m.measurementNumber); const groupObject = _.groupBy(measurements, m => m.measurementNumber);
@ -238,7 +247,7 @@ class MeasurementApi {
} }
deleteMeasurements(measurementTypeId, filter) { deleteMeasurements(measurementTypeId, filter) {
const collection = this[measurementTypeId]; const collection = this.tools[measurementTypeId];
// Get the entries information before removing them // Get the entries information before removing them
const entries = collection.find(filter).fetch(); const entries = collection.find(filter).fetch();
@ -295,13 +304,13 @@ class MeasurementApi {
} }
fetch(measurementTypeId, selector, options) { fetch(measurementTypeId, selector, options) {
if (!this[measurementTypeId]) { if (!this.tools[measurementTypeId]) {
throw 'MeasurementApi: No Collection with the id: ' + measurementTypeId; throw 'MeasurementApi: No Collection with the id: ' + measurementTypeId;
} }
selector = selector || {}; selector = selector || {};
options = options || {}; options = options || {};
return this[measurementTypeId].find(selector, options).fetch(); return this.tools[measurementTypeId].find(selector, options).fetch();
} }
} }

View File

@ -16,7 +16,7 @@ class MeasurementHandlers {
const measurementData = eventData.measurementData; const measurementData = eventData.measurementData;
const measurementToolConfiguration = config.measurementTools[index]; const measurementToolConfiguration = config.measurementTools[index];
const measurementApi = instance.data.measurementApi; const measurementApi = instance.data.measurementApi;
const Collection = measurementApi[measurementToolConfiguration.id]; const Collection = measurementApi.tools[measurementToolConfiguration.id];
// Get the Cornerstone imageId // Get the Cornerstone imageId
const enabledElement = cornerstone.getEnabledElement(eventData.element); const enabledElement = cornerstone.getEnabledElement(eventData.element);
@ -90,7 +90,7 @@ class MeasurementHandlers {
// TODO: Fix this it is a terrible workaround but we have a demo to do // TODO: Fix this it is a terrible workaround but we have a demo to do
if (baseline) { if (baseline) {
measurementApi.sortMeasurements(baseline.timepointId); measurementApi.sortMeasurements(baseline.timepointId);
} }
} }
} }
@ -108,7 +108,7 @@ class MeasurementHandlers {
const measurementToolConfiguration = config.measurementTools[index]; const measurementToolConfiguration = config.measurementTools[index];
const measurementApi = instance.data.measurementApi; const measurementApi = instance.data.measurementApi;
const Collection = measurementApi[measurementToolConfiguration.id]; const Collection = measurementApi.tools[measurementToolConfiguration.id];
OHIF.log.info('CornerstoneToolsMeasurementModified'); OHIF.log.info('CornerstoneToolsMeasurementModified');
@ -124,7 +124,7 @@ class MeasurementHandlers {
// If the measurement configuration includes a value for Viewport, // If the measurement configuration includes a value for Viewport,
// we will populate this with the Cornerstone Viewport // we will populate this with the Cornerstone Viewport
if (measurementToolConfiguration.schema.schema('viewport')) { if (measurementToolConfiguration.schema.schema('viewport')) {
measurement.viewport = cornerstone.getViewport(eventData.element); measurement.viewport = cornerstone.getViewport(eventData.element);
} }
// Clean the measurement according to the Schema // Clean the measurement according to the Schema
@ -154,7 +154,7 @@ class MeasurementHandlers {
const measurementToolConfiguration = config.measurementTools[index]; const measurementToolConfiguration = config.measurementTools[index];
const measurementApi = instance.data.measurementApi; const measurementApi = instance.data.measurementApi;
const Collection = measurementApi[measurementToolConfiguration.id]; const Collection = measurementApi.tools[measurementToolConfiguration.id];
Collection.remove(measurementData._id); Collection.remove(measurementData._id);

View File

@ -3,13 +3,6 @@ import { Blaze } from 'meteor/blaze';
import { _ } from 'meteor/underscore'; import { _ } from 'meteor/underscore';
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
const toolMap = {
bidirectional: 'targets',
targetCR: 'targets',
targetUN: 'targets',
targetEX: 'targets'
};
OHIF.measurements.toggleLabelButton = options => { OHIF.measurements.toggleLabelButton = options => {
const removeButtonView = () => { const removeButtonView = () => {
if (!options.instance.buttonView) { if (!options.instance.buttonView) {
@ -24,8 +17,8 @@ OHIF.measurements.toggleLabelButton = options => {
removeButtonView(); removeButtonView();
} }
const tool = options.measurementTypeId || toolMap[options.toolType]; const tool = options.toolType;
const toolCollection = options.measurementApi[tool]; const toolCollection = options.measurementApi.tools[tool];
const measurement = toolCollection.findOne(options.measurementId); const measurement = toolCollection.findOne(options.measurementId);
const data = { const data = {