LT-350: remove measurements from the viewport

This commit is contained in:
Leonardo Campos 2017-01-12 01:53:09 -02:00
parent 9a11dc1808
commit 98e8cf4eca
9 changed files with 165 additions and 78 deletions

View File

@ -3,11 +3,13 @@ import { SimpleSchema } from 'meteor/aldeed:simple-schema';
export const ToolGroupBaseSchema = new SimpleSchema({
toolId: {
type: String,
label: 'Tool ID'
label: 'Tool ID',
optional: true
},
toolItemId: {
type: String,
label: 'Tool Item ID'
label: 'Tool Item ID',
optional: true
},
createdAt: {
type: Date

View File

@ -15,16 +15,8 @@
imageId = enabledElement.image.imageId;
}
var enabledElements = cornerstone.getEnabledElementsByImageId(imageId);
enabledElements.forEach(function(enabledElement) {
var element = enabledElement.element;
// The HandleMeasurementRemoved handler should do the rest
cornerstoneTools.removeToolState(element, toolType, data);
//Update element
cornerstone.updateImage(element);
});
cornerstoneTools.removeToolState(element, toolType, data);
cornerstone.updateImage(element);
}
// TODO = Check if we have the same function already in Cornerstone Tools
@ -32,7 +24,7 @@
var allTools = toolManager.getTools();
var pointNearTool = false;
var touchDevice = isTouchDevice();
var nearbyTool,
var nearbyTool = {},
nearbyToolIndex,
nearbyToolType;
@ -54,9 +46,9 @@
if (toolInterface.pointNearTool(element, data, coords)) {
pointNearTool = true;
nearbyTool = data;
nearbyToolIndex = i;
nearbyToolType = toolType;
nearbyTool.tool = data;
nearbyTool.index = i;
nearbyTool.toolType = toolType;
break;
}
}
@ -66,17 +58,12 @@
}
});
if (pointNearTool === true) {
return {
nearbyTool: nearbyTool,
nearbyToolIndex: nearbyToolIndex,
nearbyToolType: nearbyToolType
};
}
return pointNearTool ? nearbyTool : undefined;
}
function keyDownCallback(e, eventData) {
var keyCode = eventData.which;
if (keyCode === keys.DELETE ||
(keyCode === keys.D && eventData.event.ctrlKey === true)) {
@ -87,12 +74,17 @@
return;
}
const dialogSettings = {
title: 'Delete measurements',
message: 'Are you sure you want to delete this measurement?'
};
// TODO= Refactor this so the confirmation dialog is an
// optional settable callback in the tool's configuration
showConfirmDialog(function() {
removeMeasurementTimepoint(nearbyToolData.nearbyTool,
nearbyToolData.nearbyToolIndex,
nearbyToolData.nearbyToolType,
OHIF.ui.showFormDialog('dialogConfirm', dialogSettings).then(() => {
removeMeasurementTimepoint(nearbyToolData.tool,
nearbyToolData.index,
nearbyToolData.toolType,
eventData.element
);
});

View File

@ -17,7 +17,7 @@ OHIF.lesiontracker.toggleLesionTrackerTools = () => {
// Hide the tools (set them all to disabled)
const toolDefaultStates = {
activate: [], //'deleteLesionKeyboardTool'
activate: ['deleteLesionKeyboardTool'],
deactivate: [],
enable: [],
disable: [ 'bidirectional', 'nonTarget', 'length', 'targetCR', 'targetUN', 'targetEX' ]

View File

@ -39,7 +39,7 @@ Meteor.startup(function() {
let newDefaultStates = {
enable: [ 'scaleOverlayTool' ],
deactivate: ['bidirectional', 'nonTarget', 'length', 'targetCR', 'targetUN', 'targetEX'],
activate: [] // 'deleteLesionKeyboardTool'
activate: ['deleteLesionKeyboardTool']
};
for (let state in newDefaultStates) {

View File

@ -37,13 +37,37 @@ class MeasurementApi {
this.toolsGroupsMap[tool.id] = toolGroup.id;
const addedHandler = measurement => {
let measurementNumber;
// Get the measurement number
const timepoint = this.timepointApi.timepoints.findOne({
studyInstanceUids: measurement.studyInstanceUid
});
const measurementNumber = groupCollection.find({
studyInstanceUid: { $in: timepoint.studyInstanceUids }
}).count() + 1;
const emptyItem = groupCollection.findOne({
toolId: { $eq: null },
timepointId: timepoint.timepointId
});
if (emptyItem) {
measurementNumber = emptyItem.measurementNumber;
groupCollection.update({
timepointId: timepoint.timepointId,
measurementNumber
}, {
$set: {
toolId: tool.id,
toolItemId: measurement._id,
createdAt: measurement.createdAt
}
});
} else {
measurementNumber = groupCollection.find({
studyInstanceUid: { $in: timepoint.studyInstanceUids }
}).count() + 1;
}
measurement.measurementNumber = measurementNumber;
// Get the current location (if already defined)
@ -60,16 +84,6 @@ class MeasurementApi {
}
}
// Reflect the entry in the tool group collection
groupCollection.insert({
toolId: tool.id,
toolItemId: measurement._id,
timepointId: timepoint.timepointId,
studyInstanceUid: measurement.studyInstanceUid,
createdAt: measurement.createdAt,
measurementNumber
});
// Set the timepoint ID, measurement number and location
collection.update(measurement._id, {
$set: {
@ -79,39 +93,74 @@ class MeasurementApi {
}
});
if (!emptyItem) {
// Reflect the entry in the tool group collection
groupCollection.insert({
toolId: tool.id,
toolItemId: measurement._id,
timepointId: timepoint.timepointId,
studyInstanceUid: measurement.studyInstanceUid,
createdAt: measurement.createdAt,
measurementNumber
});
}
// Enable reactivity
this.changeObserver.changed();
};
const removedHandler = measurement => {
// Remove the record from the tools group collection too
groupCollection.remove({
const measurementNumber = measurement.measurementNumber;
groupCollection.update({
toolItemId: measurement._id
}, {
$set: {
toolId: null,
toolItemId: null
}
});
// Update the measurement numbers only if it is last item
const measurementNumber = measurement.measurementNumber;
const timepoint = this.timepointApi.timepoints.findOne({
timepointId: measurement.timepointId
const nonEmptyItem = groupCollection.findOne({
measurementNumber,
toolId: { $not: null }
});
const filter = {
studyInstanceUid: { $in: timepoint.studyInstanceUids },
measurementNumber
};
const remainingItems = groupCollection.find(filter).count();
if (!remainingItems) {
filter.measurementNumber = { $gte: measurementNumber };
const operator = {
$inc: { measurementNumber: -1 }
};
const options = { multi: true };
groupCollection.update(filter, operator, options);
toolGroup.childTools.forEach(childTool => {
const collection = this.tools[childTool.id];
collection.update(filter, operator, options);
});
if (nonEmptyItem) {
return;
}
const groupItems = groupCollection.find({ measurementNumber }).fetch();
groupItems.forEach(groupItem => {
// Remove the record from the tools group collection too
groupCollection.remove({ _id: groupItem._id });
// Update the measurement numbers only if it is last item
const timepoint = this.timepointApi.timepoints.findOne({
timepointId: groupItem.timepointId
});
const filter = {
studyInstanceUid: { $in: timepoint.studyInstanceUids },
measurementNumber
};
const remainingItems = groupCollection.find(filter).count();
if (!remainingItems) {
filter.measurementNumber = { $gte: measurementNumber };
const operator = {
$inc: { measurementNumber: -1 }
};
const options = { multi: true };
groupCollection.update(filter, operator, options);
toolGroup.childTools.forEach(childTool => {
const collection = this.tools[childTool.id];
collection.update(filter, operator, options);
});
}
});
// Enable reactivity
this.changeObserver.changed();
};
@ -258,6 +307,8 @@ class MeasurementApi {
// Synchronize the updated measurements with Cornerstone Tools
// toolData to make sure the displayed measurements show 'Target X' correctly
const syncFilter = _.clone(filter);
delete syncFilter.timepointId;
syncFilter.measurementNumber = {
$gt: measurementNumber - 1
};
@ -281,7 +332,12 @@ class MeasurementApi {
const result = [];
const items = this.toolGroups[toolGroupId].find(selector, options).fetch();
items.forEach(item => {
result.push(this.tools[item.toolId].findOne(item.toolItemId));
if(item.toolId) {
result.push(this.tools[item.toolId].findOne(item.toolItemId));
} else {
result.push({ measurementNumber: item.measurementNumber });
}
});
return result;
}

View File

@ -124,7 +124,6 @@ class TimepointApi {
});
}
// Return the prior timepoint
lock() {
const current = this.current();
if (!current) {
@ -138,6 +137,7 @@ class TimepointApi {
});
}
// Return the prior timepoint
prior() {
const current = this.current();
if (!current) {

View File

@ -70,17 +70,40 @@ Template.measurementTableTimepointCell.events({
const rowItem = instance.data.rowItem;
const timepoints = instance.data.timepoints.get();
OHIF.measurements.jumpToRowItem(rowItem, timepoints);
}/*,
},
'keydown .measurementTableTimepointCell'(event, instance) {
const keyCode = event.which;
if (keyCode === keys.DELETE ||
(keyCode === keys.D && e.ctrlKey === true)) {
const currentMeasurement = Template.parentData(1).rowItem;
const currentTimepointID = this.timepointId;
showConfirmDialog(function() {
OHIF.lesiontracker.clearMeasurementTimepointData(currentMeasurement._id, currentTimepointID);
if (keyCode === keys.DELETE || keyCode === keys.BACKSPACE || (keyCode === keys.D && event.ctrlKey === true)) {
const currentMeasurement = Template.parentData(1).rowItem;
const timepointId = this.timepointId;
const dialogSettings = {
title: 'Delete measurements',
message: 'Are you sure you want to delete this measurement?'
};
OHIF.ui.showFormDialog('dialogConfirm', dialogSettings).then(() => {
const measurementTypeId = instance.data.rowItem.measurementTypeId;
const measurement = instance.data.rowItem.entries[0];
const measurementNumber = measurement.measurementNumber;
const measurementApi = instance.data.measurementApi;
const timepointApi = instance.data.timepointApi;
// Remove all the measurements with the given type and number
measurementApi.deleteMeasurements(measurementTypeId, {
measurementNumber,
timepointId
});
// Sync the new measurement data with cornerstone tools
const baseline = timepointApi.baseline();
measurementApi.sortMeasurements(baseline.timepointId);
// Repaint the images on all viewports without the removed measurements
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
});
}
}*/
}
});

View File

@ -4,7 +4,6 @@
theme('border-left', '%s solid $uiBorderColor' % $uiBorderThickness)
theme('color', '$textPrimaryColor')
padding: 0 10px
outline: none
cursor: pointer
&:hover

View File

@ -114,11 +114,26 @@ class MeasurementHandlers {
static onRemoved(e, instance, eventData) {
OHIF.log.info('CornerstoneToolsMeasurementRemoved');
const measurementData = eventData.measurementData;
const measurementNumber = measurementData.measurementNumber;
const measurementApi = instance.data.measurementApi;
const Collection = measurementApi.tools[eventData.toolType];
const timepointApi = instance.data.timepointApi;
const collection = measurementApi.tools[eventData.toolType];
const measurementTypeId = measurementApi.toolsGroupsMap[measurementData.toolType];
const measurement = collection.findOne(measurementData._id);
const timepointId = measurement.timepointId;
// Remove the measurement from the collection
Collection.remove(measurementData._id);
// Remove all the measurements with the given type and number
measurementApi.deleteMeasurements(measurementTypeId, {
measurementNumber,
timepointId
});
// Sync the new measurement data with cornerstone tools
const baseline = timepointApi.baseline();
measurementApi.sortMeasurements(baseline.timepointId);
// Repaint the images on all viewports without the removed measurements
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
// Signal unsaved changes
OHIF.ui.unsavedChanges.set('viewer.studyViewer.measurements.' + eventData.toolType);