Added Measurements Observe hook to repopulate toolData from database. Refactored lesion tools and lesionTable.

This commit is contained in:
Erik Ziegler committed 2015-11-22 17:17:42 +01:00
1 parent 9ad2ccaaaf
commit c178505d38
9 files changed
+481 -609

No files matched your search

@@ -1,4 +1,3 @@
var activeLesionMeasurementData;
var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneTools) {
"use strict";
@@ -66,6 +65,8 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
$(element).on('CornerstoneToolsMouseDown', eventData, cornerstoneTools.lesion.mouseDownCallback);
$(element).on('CornerstoneToolsMouseDownActivate', eventData, cornerstoneTools.lesion.mouseDownActivateCallback);
cornerstone.updateImage(element);
updateLesionCollection(measurementData);
});
}
@@ -179,20 +180,8 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
return cornerstoneMath.point.insideRect(coords, handle.boundingBox);
}
function subscribeLesionToolSelectedEvent(element) {
var elementEvents = $._data(element, "events");
var index = Object.keys(elementEvents).indexOf("LesionToolSelected");
if (index < 0) {
// Subscribe LesionToolSelected and calls loadImage when lesion measurement is changed or updated.
$(element).on("LesionToolSelected", loadImage);
}
}
///////// BEGIN IMAGE RENDERING ///////
function onImageRendered(e, eventData) {
subscribeLesionToolSelectedEvent(e.currentTarget);
// if we have no toolData for this element, return immediately as there is nothing to do
var toolData = cornerstoneTools.getToolState(e.currentTarget, toolType);
if (!toolData) {
@@ -203,13 +192,91 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
var context = eventData.canvasContext.canvas.getContext('2d');
context.setTransform(1, 0, 0, 1, 0, 0);
var color;
var element = eventData.element;
var lineWidth = cornerstoneTools.toolStyle.getToolWidth();
var config = cornerstoneTools.lesion.getConfiguration();
for (var i = 0; i < toolData.data.length; i++) {
renderLesion(toolData.data[i], context, eventData);
var data = toolData.data[i];
context.save();
// configurable shadow from CornerstoneTools
if (config && config.shadow) {
context.shadowColor = '#000000';
context.shadowOffsetX = 1;
context.shadowOffsetY = 1;
}
if (data.active) {
color = cornerstoneTools.toolColors.getActiveColor();
} else {
color = cornerstoneTools.toolColors.getToolColor();
}
// draw the line
var handleStartCanvas = cornerstone.pixelToCanvas(element, data.handles.start);
var handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
var canvasTextLocation = cornerstone.pixelToCanvas(element, data.handles.textBox);
context.beginPath();
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.moveTo(handleStartCanvas.x, handleStartCanvas.y);
context.lineTo(handleEndCanvas.x, handleEndCanvas.y);
context.stroke();
// draw the handles
cornerstoneTools.drawHandles(context, eventData, data.handles, color);
if (data.lesionName) {
//Draw linked line as dashed
context.beginPath();
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.setLineDash([2, 3]);
var mid = {
x: (handleStartCanvas.x + handleEndCanvas.x) / 2,
y: (handleStartCanvas.y + handleEndCanvas.y) / 2
};
context.moveTo(mid.x, mid.y);
context.lineTo(canvasTextLocation.x + 20, canvasTextLocation.y + 20);
context.stroke();
// Draw the text
var dx = (data.handles.start.x - data.handles.end.x) * (eventData.image.columnPixelSpacing || 1);
var dy = (data.handles.start.y - data.handles.end.y) * (eventData.image.rowPixelSpacing || 1);
var length = Math.sqrt(dx * dx + dy * dy);
var suffix = ' mm';
if (!eventData.image.rowPixelSpacing || !eventData.image.columnPixelSpacing) {
suffix = ' pixels';
}
var text = '' + length.toFixed(2) + suffix;
var textLines = [data.lesionName, text];
var boundingBox = cornerstoneTools.drawTextBox(context,
textLines,
canvasTextLocation.x, canvasTextLocation.y, color);
data.handles.textBox.boundingBox = boundingBox;
// Set measurement text to show lesion table
data.measurementText = length.toFixed(1);
}
context.restore();
updateLesionCollection(toolData.data[i]);
}
}
function updateLesionCollection(lesionData) {
// TODO = Remove this in favour of measurement events
if (!lesionData.active) {
return;
}
@@ -217,176 +284,11 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
if (lesionData.timepointID && lesionData.timepointID !== "") {
// Update Measurements Collection
measurementManagerDAL.updateTimepointData(lesionData);
} else {
activeLesionMeasurementData = lesionData;
}
}
function renderLesion(data, context, eventData) {
context.save();
var color;
var element = eventData.element;
var lineWidth = cornerstoneTools.toolStyle.getToolWidth();
var config = cornerstoneTools.lesion.getConfiguration();
// configurable shadow from CornerstoneTools
if (config && config.shadow) {
context.shadowColor = '#000000';
context.shadowOffsetX = 1;
context.shadowOffsetY = 1;
}
if (data.active) {
color = cornerstoneTools.toolColors.getActiveColor();
} else {
color = cornerstoneTools.toolColors.getToolColor();
}
// draw the line
var handleStartCanvas = cornerstone.pixelToCanvas(element, data.handles.start);
var handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
var canvasTextLocation = cornerstone.pixelToCanvas(element, data.handles.textBox);
context.beginPath();
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.moveTo(handleStartCanvas.x, handleStartCanvas.y);
context.lineTo(handleEndCanvas.x, handleEndCanvas.y);
context.stroke();
// draw the handles
cornerstoneTools.drawHandles(context, eventData, data.handles, color);
//Draw linked line as dashed
context.setLineDash([2, 3]);
context.beginPath();
context.strokeStyle = color;
context.lineWidth = 1 / eventData.viewport.scale;
var mid = {
x: (handleStartCanvas.x + handleEndCanvas.x) / 2,
y: (handleStartCanvas.y + handleEndCanvas.y) / 2
};
context.moveTo(mid.x, mid.y);
context.lineTo(canvasTextLocation.x + 20, canvasTextLocation.y + 20);
context.stroke();
// Draw the text
var dx = (data.handles.start.x - data.handles.end.x) * (eventData.image.columnPixelSpacing || 1);
var dy = (data.handles.start.y - data.handles.end.y) * (eventData.image.rowPixelSpacing || 1);
var length = Math.sqrt(dx * dx + dy * dy);
var suffix = ' mm';
if (!eventData.image.rowPixelSpacing || !eventData.image.columnPixelSpacing) {
suffix = ' pixels';
}
var text = '' + length.toFixed(2) + suffix;
var textLines = [data.lesionName, text];
var boundingBox = cornerstoneTools.drawTextBox(context,
textLines,
canvasTextLocation.x, canvasTextLocation.y, color);
data.handles.textBox.boundingBox = boundingBox;
// Set measurement text to show lesion table
data.measurementText = length.toFixed(1);
// Lesion Measurement is changed
$(element).trigger("LesionTextChanged", data);
context.restore();
}
///////// END IMAGE RENDERING ///////
function updateLesion(e, eventData) {
var enabledElement = eventData.enabledElement;
var element = eventData.enabledElement.element;
var isTarget = eventData.lesionData.isTarget;
var lesionNumber = eventData.lesionData.lesionNumber;
var type = eventData.type;
// if we have no toolData for this element, return immediately as there is nothing to do
var toolData = cornerstoneTools.getToolState(e.currentTarget, toolType);
if (!toolData) {
return;
}
var data,
i;
switch (type) {
case "delete":
//If type is delete, remove measurement
var deletedDataIndex = -1;
for (i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
//When click a row of table measurements, measurement will be active and color will be green
if (data.lesionNumber === lesionNumber && eventData.type !== "active" && isTarget) {
data.visible = false;
deletedDataIndex = i;
}
}
if (deletedDataIndex >= 0 && deletedDataIndex < toolData.data.length) {
toolData.data.splice(deletedDataIndex, 1);
}
break;
case "active":
for (i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
//When click a row of table measurements, measurement will be active and color will be green
if (data.lesionNumber === lesionNumber && eventData.type === "active" && isTarget) {
data.active = true;
} else {
data.active = false;
}
}
break;
case "inactive":
for (i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
// Make inactive all lesions for the timepoint
data.active = false;
}
break;
}
cornerstone.updateImage(element);
}
// TODO=Refactor because this function is repeated in nonTargetTool!
function loadImage(e, eventData) {
// If type is active, load image and activate lesion
// If type is inactive, update lesions of enabledElement as inactive
log.info('lesionTool loadImage');
var element = eventData.enabledElement.element;
var imageId = eventData.lesionData.imageId;
if (eventData.type === "active") {
var stackToolDataSource = cornerstoneTools.getToolState(element, 'stack');
var stackData = stackToolDataSource.data[0];
var imageIdIndex = stackData.imageIds.indexOf(imageId);
if (imageIdIndex < 0) {
return;
}
cornerstone.loadAndCacheImage(imageIds[imageIdIndex]).then(function(image) {
cornerstone.displayImage(element, image);
updateLesion(e, eventData);
});
} else if (eventData.type === "inactive") {
updateLesion(e, eventData);
}
}
// module exports
cornerstoneTools.lesion = cornerstoneTools.mouseButtonTool({
createNewMeasurement: createNewMeasurement,
@@ -23,8 +23,8 @@ var measurementManagerDAL = (function() {
longestDiameter: lesionData.measurementText,
imageId: lesionData.imageId,
seriesInstanceUid: lesionData.seriesInstanceUid,
studyInstanceUid: lesionData.studyInstanceUid
studyInstanceUid: lesionData.studyInstanceUid,
handles: lesionData.handles
};
} else {
// Add null measurement
@@ -32,22 +32,25 @@ var measurementManagerDAL = (function() {
longestDiameter: "",
imageId: "",
seriesInstanceUid: "",
studyInstanceUid: ""
studyInstanceUid: "",
handles: undefined
};
}
timepointsObject[timepointId] = timepointObject;
}
var lesionDataObject = {
patientId: timepoints[0].patientId,
lesionUID: uuid.v4(),
number: Measurements.find().count() + 1,
lesionNumber: lesionData.lesionNumber,
isTarget: lesionData.isTarget,
locationUID: lesionData.locationUID,
location: getLocationName(lesionData.locationUID),
timepoints: timepointsObject
};
var lesionDataObject = lesionData;
lesionDataObject.patientId = timepoints[0].patientId;
lesionDataObject.location = getLocationName(lesionData.locationUID);
lesionDataObject.timepoints = timepointsObject;
// Is there a use for this?
lesionDataObject.number = Measurements.find().count() + 1;
// TODO=Fix this workaround to prevent the observe hook from adding another set of toolData
lesionDataObject.toolDataInsertedManually = true;
Measurements.insert(lesionDataObject);
}
@@ -36,7 +36,7 @@
var element = mouseEventData.element;
function doneCallback(lesionNumber) {
measurementData.lesionName = "Non-Target "+lesionNumber;
measurementData.lesionName = "Non-Target " + lesionNumber;
measurementData.lesionNumber = lesionNumber;
measurementData.active = true;
cornerstone.updateImage(element);
@@ -152,142 +152,88 @@
return cornerstoneMath.point.insideRect(coords, handle.boundingBox);
}
function drawArrow(context, start, end, color, lineWidth) {
//variables to be used when creating the arrow
var headLength = 10;
var angle = Math.atan2(end.y - start.y, end.x - start.x);
//starting path of the arrow from the start square to the end square and drawing the stroke
context.beginPath();
context.moveTo(start.x, start.y);
context.lineTo(end.x, end.y);
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.stroke();
//starting a new path from the head of the arrow to one of the sides of the point
context.beginPath();
context.moveTo(end.x, end.y);
context.lineTo(end.x - headLength * Math.cos(angle - Math.PI / 7), end.y - headLength * Math.sin(angle - Math.PI / 7));
//path from the side point of the arrow, to the other side point
context.lineTo(end.x - headLength * Math.cos(angle + Math.PI / 7), end.y - headLength * Math.sin(angle + Math.PI / 7));
//path from the side point back to the tip of the arrow, and then again to the opposite side point
context.lineTo(end.x, end.y);
context.lineTo(end.x - headLength * Math.cos(angle - Math.PI / 7), end.y - headLength * Math.sin(angle - Math.PI / 7));
//draws the paths created above
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.stroke();
context.fillStyle = color;
context.fill();
}
function subscribeNonTargetToolModifiedEvent(element) {
var elementEvents = $._data(element, "events");
var index = Object.keys(elementEvents).indexOf("NonTargetToolSelected");
if (index < 0) {
// Subscribe LesionToolModified and calls loadImage function when lesion measurement is changed or updated.
$(element).on("NonTargetToolSelected", loadImage);
}
}
///////// BEGIN IMAGE RENDERING ///////
function onImageRendered(e, eventData) {
subscribeNonTargetToolModifiedEvent(e.currentTarget);
var element = eventData.element;
// if we have no toolData for this element, return immediately as there is nothing to do
var toolData = cornerstoneTools.getToolState(e.currentTarget, toolType);
if (toolData === undefined) {
var toolData = cornerstoneTools.getToolState(element, toolType);
if (!toolData) {
return;
}
updateLesions(toolData, eventData);
}
function updateLesions(toolData, eventData) {
// we have tool data for this element - iterate over each one and draw it
var context = eventData.canvasContext.canvas.getContext('2d');
context.setTransform(1, 0, 0, 1, 0, 0);
for (var i = 0; i < toolData.data.length; i++) {
renderLesion(toolData.data[i], context, eventData);
}
}
function renderLesion(lesion, context, eventData) {
context.save();
var color;
var lineWidth = cornerstoneTools.toolStyle.getToolWidth();
var font = cornerstoneTools.textStyle.getFont();
var config = cornerstoneTools.nonTarget.getConfiguration();
// configurable shadow from CornerstoneTools
if (config && config.shadow) {
context.shadowColor = '#000000';
context.shadowOffsetX = +1;
context.shadowOffsetY = +1;
context.font = font;
for (var i = 0; i < toolData.data.length; i++) {
var data = toolData.data[i];
context.save();
// configurable shadow from CornerstoneTools
if (config && config.shadow) {
context.shadowColor = '#000000';
context.shadowOffsetX = +1;
context.shadowOffsetY = +1;
}
if (data.active) {
color = cornerstoneTools.toolColors.getActiveColor();
} else {
color = cornerstoneTools.toolColors.getToolColor();
}
// Draw the arrow
var handleStartCanvas = cornerstone.pixelToCanvas(element, data.handles.start);
var handleEndCanvas = cornerstone.pixelToCanvas(element, data.handles.end);
var canvasTextLocation = cornerstone.pixelToCanvas(element, data.handles.textBox);
if (config.arrowFirst) {
cornerstoneTools.drawArrow(context, handleEndCanvas, handleStartCanvas, color, lineWidth);
} else {
cornerstoneTools.drawArrow(context, handleStartCanvas, handleEndCanvas, color, lineWidth);
}
if (config.drawHandles) {
cornerstoneTools.drawHandles(context, eventData, data.handles, color);
} else if (config.drawHandlesOnHover && data.handles.start.active) {
cornerstoneTools.drawHandles(context, eventData, [ lesion.handles.start ], color);
} else if (config.drawHandlesOnHover && data.handles.end.active) {
cornerstoneTools.drawHandles(context, eventData, [ lesion.handles.end ], color);
}
// Draw the text
if (data.lesionName && data.lesionName !== '') {
//Draw linked line as dashed
var mid = {
x: (handleStartCanvas.x + handleEndCanvas.x) / 2,
y: (handleStartCanvas.y + handleEndCanvas.y) / 2
};
context.beginPath();
context.strokeStyle = color;
context.lineWidth = lineWidth;
context.setLineDash([2, 3]);
context.moveTo(mid.x, mid.y);
context.lineTo(canvasTextLocation.x + 20, canvasTextLocation.y + 20);
context.stroke();
var boundingBox = cornerstoneTools.drawTextBox(context, data.lesionName, canvasTextLocation.x, canvasTextLocation.y, color);
data.handles.textBox.boundingBox = boundingBox;
}
context.restore();
}
if (lesion.active) {
color = cornerstoneTools.toolColors.getActiveColor();
} else {
color = cornerstoneTools.toolColors.getToolColor();
}
// Draw the arrow
var handleStartCanvas = cornerstone.pixelToCanvas(eventData.element, lesion.handles.start);
var handleEndCanvas = cornerstone.pixelToCanvas(eventData.element, lesion.handles.end);
var canvasTextLocation = cornerstone.pixelToCanvas(eventData.element, lesion.handles.textBox);
if (config.arrowFirst) {
drawArrow(context, handleEndCanvas, handleStartCanvas, color, lineWidth);
} else {
drawArrow(context, handleStartCanvas, handleEndCanvas, color, lineWidth);
}
if (config.drawHandles) {
cornerstoneTools.drawHandles(context, eventData, lesion.handles, color);
} else if (config.drawHandlesOnHover && lesion.handles.start.active) {
cornerstoneTools.drawHandles(context, eventData, [ lesion.handles.start ], color);
} else if (config.drawHandlesOnHover && lesion.handles.end.active) {
cornerstoneTools.drawHandles(context, eventData, [ lesion.handles.end ], color);
}
//Draw linked line as dashed
var mid = {
x: (handleStartCanvas.x + handleEndCanvas.x) / 2,
y: (handleStartCanvas.y + handleEndCanvas.y) / 2
};
context.setLineDash([2, 3]);
context.beginPath();
context.strokeStyle = color;
context.lineWidth = 1 / eventData.viewport.scale;
mid = {
x: mid.x,
y: mid.y
};
context.moveTo(mid.x, mid.y);
context.lineTo(canvasTextLocation.x + 20, canvasTextLocation.y + 20);
context.stroke();
// Draw the text
if (lesion.lesionName && lesion.lesionName !== '') {
context.font = font;
var boundingBox = cornerstoneTools.drawTextBox(context, lesion.lesionName, canvasTextLocation.x, canvasTextLocation.y, color);
lesion.handles.textBox.boundingBox = boundingBox;
}
context.restore();
}
// ---- Touch tool ----
///////// BEGIN ACTIVE TOOL ///////
@@ -295,7 +241,7 @@
var element = touchEventData.element;
function doneCallback(lesionNumber) {
measurementData.lesionName = "Non-Target "+lesionNumber;
measurementData.lesionName = "Non-Target " + lesionNumber;
measurementData.lesionNumber = lesionNumber;
measurementData.active = true;
cornerstone.updateImage(element);
@@ -377,114 +323,6 @@
return false; // false = causes jquery to preventDefault() and stopPropagation() this event
}
function updateLesion(e, eventObject) {
var start = new Date();
var enabledElement = eventObject.enabledElement;
var isTarget = eventObject.lesionData.isTarget;
var lesionNumber = eventObject.lesionData.lesionNumber;
var seriesInstanceUid = eventObject.lesionData.seriesInstanceUid;
var studyInstanceUid = eventObject.lesionData.studyInstanceUid;
var type = eventObject.type;
// if we have no toolData for this element, return immediately as there is nothing to do
var toolData = cornerstoneTools.getToolState(e.currentTarget, toolType);
if (!toolData) {
return;
}
//If type is delete, remove measurement
if (type === "delete") {
var deletedDataIndex = -1;
for (var i = 0; i < toolData.data.length; i++) {
var data = toolData.data[i];
//When click a row of table measurements, measurement will be active and color will be green
if (data.lesionNumber === lesionNumber
&& eventObject.type !== "active"
&& !isTarget
&& data.seriesInstanceUid === seriesInstanceUid
&& data.studyInstanceUid === studyInstanceUid) {
data.visible = false;
deletedDataIndex = i;
}
}
if (deletedDataIndex >= 0 && deletedDataIndex < toolData.data.length) {
toolData.data.splice(deletedDataIndex, 1);
}
} else if (type === "active") {
for (var i = 0; i < toolData.data.length; i++) {
var data = toolData.data[i];
//When click a row of table measurements, measurement will be active and color will be green
if (data.lesionNumber === eventObject.lesionData.lesionNumber
&& eventObject.type === "active"
&& !isTarget
&& data.seriesInstanceUid === seriesInstanceUid
&& data.studyInstanceUid === studyInstanceUid) {
data.active = true;
} else {
data.active = false;
}
}
} else if (type === "inactive") {
for (var i = 0; i < toolData.data.length; i++) {
var data = toolData.data[i];
// Make inactive all lesions for the timepoint
data.active = false;
}
}
var context = enabledElement.canvas.getContext('2d');
var end = new Date();
var diff = end - start;
//console.log(diff + ' ms');
var eventData = {
viewport: enabledElement.viewport,
element: enabledElement.element,
image: enabledElement.image,
enabledElement: enabledElement,
canvasContext: context,
measurementText: "",
renderTimeInMs: diff,
lesionNumber: lesionNumber,
isTarget: isTarget,
type: type //Holds image will be deleted or active
};
enabledElement.invalid = false;
onImageRendered(e, eventData);
}
function loadImage(e, eventData) {
// If type is active, load image and activate lesion
// If type is inactive, update lesions of enabledElement as inactive
log.info('nonTargetTool loadImage');
var element = eventData.enabledElement.element;
var imageId = eventData.lesionData.imageId;
if (eventData.type === "active") {
var stackToolDataSource = cornerstoneTools.getToolState(element, 'stack');
var stackData = stackToolDataSource.data[0];
var imageIdIndex = stackData.imageIds.indexOf(imageId);
if (imageIdIndex < 0) {
return;
}
cornerstone.loadAndCacheImage(stackData.imageIds[imageIdIndex]).then(function(image) {
cornerstone.displayImage(element, image);
updateLesion(e, eventData);
});
} else if (eventData.type === "inactive") {
updateLesion(e, eventData);
}
}
cornerstoneTools.nonTarget = cornerstoneTools.mouseButtonTool({
addNewMeasurement: addNewMeasurement,
createNewMeasurement: createNewMeasurement,
@@ -1,74 +1,3 @@
/**
* Returns timepoint object based on timepoint id of the enabled element
*
* @param timepoints
* @param enabledElement
* @returns {*|{}} Timepoint object based on timepoint id of the enabled element (or an empty Object)
*/
function getTimepointObject(imageId) {
var study = cornerstoneTools.metaData.get('study', imageId);
var timepoint = Timepoints.findOne({timepointName: study.studyDate});
return timepoint;
}
/**
* Switch to the image of the correct image index
* Activate the selected measurement on the switched image (color to be green)
* Deactivate all other measurements on the switched image (color to be white)
*/
function activateMeasurements(element, measurementId) {
// TODO=Switch this to use the new CornerstoneToolMeasurementModified event,
// Once it has 'modified on activation' set up
var enabledElement = cornerstone.getEnabledElement(element);
var imageId = enabledElement.image.imageId;
var timepointData = getTimepointObject(imageId);
var measurementData = Measurements.findOne(measurementId);
var measurementAtTimepoint = measurementData.timepoints[timepointData.timepointID];
if (!measurementAtTimepoint) {
return;
}
// Defines event data
var eventData = {
enabledElement: enabledElement,
lesionData: {
id: measurementId,
isTarget: measurementData.isTarget,
lesionNumber: measurementData.lesionNumber,
imageId: imageId,
seriesInstanceUid: measurementAtTimepoint.seriesInstanceUid,
studyInstanceUid: measurementAtTimepoint.studyInstanceUid
},
type: "active"
};
// If isTarget = false, this measurement is nonTarget measurement
// Activate related nonTarget measurement
// Deactivate all target measurements to activate only nonTarget measurement
if (!isTarget) {
$(element).trigger("NonTargetToolSelected", eventData);
// Deactivate lesion tool measurements
eventData.type = "inactive";
$(element).trigger("LesionToolSelected", eventData);
} else {
// Trigger event for target measurements
$(element).trigger("LesionToolSelected", eventData);
// Deactivate nonTarget tool measurements
eventData.type = "inactive";
// Trigger event for nonTarget measurements
// Inactivate all nonTarget measurements if any measurement is active
$(element).trigger("NonTargetToolSelected", eventData);
}
}
/**
* Activates a set of lesions when lesion table row is clicked
*
@@ -87,25 +16,45 @@ function activateLesion(measurementId) {
// Get the timepoint data from this Measurement
var timepoints = measurementData.timepoints;
// Get all non-dummy timepoint entries in the Measurement
// TODO=Re-evaluate this approach to populating viewports with timepoints
// What is the desired behaviour here?
var timepointsWithEntries = [];
Object.keys(timepoints).forEach(function(key) {
var timepoint = timepoints[key];
if (timepoint.imageId === "" ||
timepoint.studyInstanceUid === "" ||
timepoint.seriesInstanceUid === "") {
return;
}
timepointsWithEntries.push(timepoint);
});
// If there are no non-dummy timepoint entries, stop here
if (!timepointsWithEntries.length) {
return;
}
// Loop through the viewports and display each timepoint
$(".imageViewerViewport").each(function(viewportIndex, element) {
// Stop if we run out of timepoints before viewports
if (viewportIndex >= Object.keys(timepoints).length) {
if (viewportIndex >= timepointsWithEntries.length) {
return false;
}
// Find measurements related to the Nth timepoint
// TODO=Re-evaluate this approach to populating viewports with timepoints
// What is the desired behaviour here?
var measurementAtTimepoint = timepointsWithEntries[viewportIndex];
// Find the image that is currently in this viewport
var enabledElement = cornerstone.getEnabledElement(element);
if (!enabledElement || !enabledElement.image) {
return;
}
// Find measurements related to the Nth timepoint
// TODO=Re-evaluate this approach to populating viewports with timepoints
// What is the desired behaviour here?
var key = Object.keys(measurementData.timepoints)[viewportIndex];
var measurementAtTimepoint = measurementData.timepoints[key];
// If there is no measurement data to display, stop here
if (!measurementAtTimepoint) {
return;
@@ -134,6 +83,115 @@ function activateLesion(measurementId) {
});
}
/**
* Returns timepoint object based on timepoint id of the enabled element
*
* @param timepoints
* @param enabledElement
* @returns {*|{}} Timepoint object based on timepoint id of the enabled element (or an empty Object)
*/
function getTimepointObject(imageId) {
var study = cornerstoneTools.metaData.get('study', imageId);
return Timepoints.findOne({timepointName: study.studyDate});
}
/**
* Switch to the image of the correct image index
* Activate the selected measurement on the switched image (color to be green)
* Deactivate all other measurements on the switched image (color to be white)
*/
function activateMeasurements(element, measurementId) {
// TODO=Switch this to use the new CornerstoneToolMeasurementModified event,
// Once it has 'modified on activation' set up
var enabledElement = cornerstone.getEnabledElement(element);
var imageId = enabledElement.image.imageId;
var timepointData = getTimepointObject(imageId);
var measurementData = Measurements.findOne(measurementId);
var measurementAtTimepoint = measurementData.timepoints[timepointData.timepointID];
if (!measurementAtTimepoint) {
return;
}
// If type is active, load image and activate lesion
// If type is inactive, update lesions of enabledElement as inactive
var stackToolDataSource = cornerstoneTools.getToolState(element, 'stack');
var stackData = stackToolDataSource.data[0];
var imageIds = stackData.imageIds;
var imageIdIndex = imageIds.indexOf(measurementAtTimepoint.imageId);
if (imageIdIndex < 0) {
return;
}
if (imageIdIndex === stackData.currentImageIdIndex){
activateTool(element, measurementData, timepointData.timepointID);
} else {
cornerstone.loadAndCacheImage(imageIds[imageIdIndex]).then(function(image) {
cornerstone.displayImage(element, image);
activateTool(element, measurementData, timepointData.timepointID);
});
}
}
/**
* Activates a specific tool data instance and deactivates all other
* target and non-target measurement data
*
* @param element
* @param measurementData
* @param timepointID
*/
function activateTool(element, measurementData, timepointID) {
deactivateAllToolData(element, 'lesion');
deactivateAllToolData(element, 'nonTarget');
var toolType = measurementData.isTarget ? 'lesion' : 'nonTarget';
var toolData = cornerstoneTools.getToolState(element, toolType);
if (!toolData) {
return;
}
var measurementAtTimepoint = measurementData.timepoints[timepointID];
for (var i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
// When click a row of table measurements, measurement will be active and color will be green
// TODO= Remove this with the measurementId once it is in the tool data
if (data.seriesInstanceUid === measurementAtTimepoint.seriesInstanceUid &&
data.studyInstanceUid === measurementAtTimepoint.studyInstanceUid &&
data.lesionNumber === measurementData.lesionNumber &&
data.isTarget == measurementData.isTarget) {
data.active = true;
break;
}
}
cornerstone.updateImage(element);
}
/**
* Sets all tool data entries value for 'active' to false
* This is used to remove the active color on entire sets of tools
*
* @param element The Cornerstone element that is being used
* @param toolType The tooltype of the tools that will be deactivated
*/
function deactivateAllToolData(element, toolType) {
var toolData = cornerstoneTools.getToolState(element, toolType);
if (!toolData) {
return;
}
for (var i = 0; i < toolData.data.length; i++) {
var data = toolData.data[i];
data.active = false;
}
}
Template.lesionTable.helpers({
'measurement': function() {
return Measurements.find({}, {sort: {number: 1}});