From f5f10dea346827f2a8ebe2c0a218118f2dbaebc1 Mon Sep 17 00:00:00 2001 From: Aysel Afsar Date: Thu, 29 Oct 2015 08:50:28 -0400 Subject: [PATCH] Measurements collection is added for lesion table --- LesionTracker/.meteor/packages | 1 + .../lesiontracker/compatibility/lesionTool.js | 280 ++++++++++++------ .../compatibility/measurementManagerDAL.js | 206 +++++++++++++ .../components/lesionDialog/lesionDialog.js | 26 +- .../lesionLocationDialog.js | 29 ++ .../components/lesionTable/lesionTable.html | 2 + .../components/lesionTable/lesionTable.js | 225 +++----------- .../components/lesionTable/lesionTable.styl | 5 +- .../lesionTableRow/lesionTableRow.html | 12 +- .../lesionTableRow/lesionTableRow.js | 4 +- .../lesiontracker/lib/getActiveTimepointID.js | 7 + Packages/lesiontracker/lib/uuid.js | 250 ++++++++++++++++ Packages/lesiontracker/package.js | 6 + .../imageViewerViewport.js | 1 + Packages/worklist/components/worklist.js | 5 + Packages/worklist/lib/generateUUID.js | 2 +- 16 files changed, 774 insertions(+), 287 deletions(-) create mode 100644 Packages/lesiontracker/compatibility/measurementManagerDAL.js create mode 100644 Packages/lesiontracker/lib/getActiveTimepointID.js create mode 100755 Packages/lesiontracker/lib/uuid.js diff --git a/LesionTracker/.meteor/packages b/LesionTracker/.meteor/packages index 808176914..b9b9c9081 100644 --- a/LesionTracker/.meteor/packages +++ b/LesionTracker/.meteor/packages @@ -34,4 +34,5 @@ stylus fortawesome:fontawesome random reactive-var +reactive-dict lesiontracker diff --git a/Packages/lesiontracker/compatibility/lesionTool.js b/Packages/lesiontracker/compatibility/lesionTool.js index 8b6b3b62b..8fab525b2 100644 --- a/Packages/lesiontracker/compatibility/lesionTool.js +++ b/Packages/lesiontracker/compatibility/lesionTool.js @@ -1,4 +1,6 @@ var lineIndex = 0; //This holds drawn line index +var activeLesionMeasurementData; +var timepointID; var cornerstoneTools = (function ($, cornerstone, cornerstoneMath, cornerstoneTools) { "use strict"; @@ -13,6 +15,9 @@ var cornerstoneTools = (function ($, cornerstone, cornerstoneMath, cornerstoneTo function createNewMeasurement(mouseEventData) { var element = mouseEventData.element; + timepointID = getActiveTimepointID(element); + var lesionNumber = measurementManagerDAL.getLesionNumber(timepointID); + console.log(lesionNumber); var lesionCounter = ""; // Subscribe CornerstoneMouseup event, when mouse is up, call lesionDialog @@ -21,8 +26,12 @@ var cornerstoneTools = (function ($, cornerstone, cornerstoneMath, cornerstoneTo // Unsubscribe CornerstoneToolsMouseUp event $(element).off("CornerstoneToolsMouseUp"); + // Set lesionMeasurementData Session + activeLesionMeasurementData.timepointID = timepointID; + Session.set("lesionMeasurementData", activeLesionMeasurementData); + // Show LesionDialog - $(document).trigger("ShowLesionDialog", e); + $(document).trigger("ShowLesionDialog", [e, activeLesionMeasurementData]); }); @@ -72,9 +81,11 @@ var cornerstoneTools = (function ($, cornerstone, cornerstoneMath, cornerstoneTo }, init: false }, - lesionName: "Target "+lesionCounter, + lesionName: "Target "+lesionNumber, isDeleted: false, - lineNumber:"" //Indicates line number on image + lineNumber:"", //Indicates line number on image + lesionNumber: lesionNumber, + uid: uuid.v4() }; lineIndex++; return measurementData; @@ -103,110 +114,201 @@ var cornerstoneTools = (function ($, cornerstone, cornerstoneMath, cornerstoneTo ///////// BEGIN IMAGE RENDERING /////// function onImageRendered(e, eventData) { - // 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) { return; } + updateLesions(toolData, eventData, e.currentTarget); + } + + function updateLesions(toolData, eventData, currentElement) { // 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); + updateLesionCollection(toolData.data[i], currentElement); + } + } + + function updateLesionCollection(lesionData, currentElement) { + + if (lesionData.active) { + activeLesionMeasurementData = lesionData; + } + + // TODO: Option1: Create a global variable like lesionMeasurementData + // TODO: Insert lesionData inside the lesionMeasurementData + // TODO: Send the lesionMeasurementData to lesionDialog by ShowLesionDialog event + + /*if (lesionMeasurementData != undefined && lesionMeasurementData.lesionNumber === lesionData.index) { + lesionMeasurementData.timepoints.now.longestDiameter = lesionData.measurementText; + console.log(lesionMeasurementData.timepoints.now.longestDiameter); + } else { + lesionMeasurementData = { + lesionNumber: lesionData.index, + isTarget: true, + location: '', + timepoints: { + "now": { + imageId: "blah", + timepointUid: "timepointX", + date: 2010, + isDirty: true, + longestDiameter: lesionData.measurementText + }, + "earlier": { + imageId: "blah2", + timepointUid: "timepointy", + date: 2010, + isDirty: true, + longestDiameter: 8 + } + } + }; + }*/ + + // TODO: Option2: + // Check collection has this lesionData + /*var isFound = Measurements.findOne({lesionNumber: lesionData.index}); + + // TODO: Decide which time point is changed + if (isFound) { + // Update measurement text + Measurements.update( + { lesionNumber: lesionData.index }, + { + $set: { + "timepoints.now.longestDiameter": lesionData.measurementText + } + }, {multi: true} + ); + + console.log(Measurements.find()); + } else { + var lesionObject = { + lesionNumber: lesionData.index, + isTarget: true, + location: '', + isHidden: true, + timepoints: { + "now": { + imageId: "blah", + timepointUid: "timepointX", + date: 2010, + isDirty: true, + longestDiameter: lesionData.measurementText + }, + "earlier": { + imageId: "blah2", + timepointUid: "timepointy", + date: 2010, + isDirty: true, + longestDiameter: 8 + } + } + }; + Measurements.insert(lesionObject); + }*/ + } + + function renderLesion(lesion, context, eventData){ + context.save(); + var color; var lineWidth = cornerstoneTools.toolStyle.getToolWidth(); var font = cornerstoneTools.textStyle.getFont(); var config = cornerstoneTools.length.getConfiguration(); - for (var i = 0; i < toolData.data.length; i++) { - context.save(); - // configurable shadow - if (config && config.shadow) { - context.shadowColor = '#000000'; - context.shadowOffsetX = +1; - context.shadowOffsetY = +1; - } - - var data = toolData.data[i]; - if (data.active) { - color = cornerstoneTools.toolColors.getActiveColor(); - } else { - color = cornerstoneTools.toolColors.getToolColor(); - } - - // draw the line - var handleStartCanvas = cornerstone.pixelToCanvas(eventData.element, data.handles.start); - var handleEndCanvas = cornerstone.pixelToCanvas(eventData.element, data.handles.end); - - 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); - - //Set coordinates of text - var linkedTextStartCanvas = cornerstone.pixelToCanvas(eventData.element, data.linkedTextCoords.start); - var linkedTextEndCanvas = cornerstone.pixelToCanvas(eventData.element, data.linkedTextCoords.end); - if(!data.linkedTextCoords.init){ - data.linkedTextCoords.start.x = data.handles.start.x + 50; - data.linkedTextCoords.start.y = data.handles.start.y + 40; - linkedTextStartCanvas = cornerstone.pixelToCanvas(eventData.element, data.linkedTextCoords.start); - - //Set end point of linkedTextCoords - data.linkedTextCoords.end.x = data.linkedTextCoords.start.x + 50; - data.linkedTextCoords.end.y = data.linkedTextCoords.start.y + 30; - linkedTextEndCanvas = cornerstone.pixelToCanvas(eventData.element, data.linkedTextCoords.end); - - //initialized coordinates of text - data.linkedTextCoords.init = true; - } - - //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(linkedTextStartCanvas.x + 20, linkedTextStartCanvas.y + 20); - context.stroke(); - - // Draw the text - context.fillStyle = color; - context.font = font; - 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 textCoords = { - x: linkedTextStartCanvas.x, y: linkedTextStartCanvas.y - }; - - cornerstoneTools.drawTextBox(context, data.lesionName, textCoords.x, textCoords.y, color); - cornerstoneTools.drawTextBox(context, text, textCoords.x, textCoords.y + 20, color); - - //Set measurement text to show lesion table - data.measurementText = length.toFixed(2); - $(eventData.enabledElement.element).trigger("LesionTextChanged",data); - - context.restore(); + // configurable shadow from CornerstoneTools + if (config && config.shadow) { + context.shadowColor = '#000000'; + context.shadowOffsetX = +1; + context.shadowOffsetY = +1; } + if (lesion.active) { + color = cornerstoneTools.toolColors.getActiveColor(); + } else { + color = cornerstoneTools.toolColors.getToolColor(); + } + + // draw the line + var handleStartCanvas = cornerstone.pixelToCanvas(eventData.element, lesion.handles.start); + var handleEndCanvas = cornerstone.pixelToCanvas(eventData.element, lesion.handles.end); + + 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, lesion.handles, color); + + //Set coordinates of text + var linkedTextStartCanvas = cornerstone.pixelToCanvas(eventData.element, lesion.linkedTextCoords.start); + var linkedTextEndCanvas = cornerstone.pixelToCanvas(eventData.element, lesion.linkedTextCoords.end); + if(!lesion.linkedTextCoords.init){ + lesion.linkedTextCoords.start.x = lesion.handles.start.x + 50; + lesion.linkedTextCoords.start.y = lesion.handles.start.y + 40; + linkedTextStartCanvas = cornerstone.pixelToCanvas(eventData.element, lesion.linkedTextCoords.start); + + //Set end point of linkedTextCoords + lesion.linkedTextCoords.end.x = lesion.linkedTextCoords.start.x + 50; + lesion.linkedTextCoords.end.y = lesion.linkedTextCoords.start.y + 30; + linkedTextEndCanvas = cornerstone.pixelToCanvas(eventData.element, lesion.linkedTextCoords.end); + + //initialized coordinates of text + lesion.linkedTextCoords.init = true; + } + + //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(linkedTextStartCanvas.x + 20, linkedTextStartCanvas.y + 20); + context.stroke(); + + // Draw the text + context.fillStyle = color; + context.font = font; + var dx = (lesion.handles.start.x - lesion.handles.end.x) * (eventData.image.columnPixelSpacing || 1); + var dy = (lesion.handles.start.y - lesion.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 textCoords = { + x: linkedTextStartCanvas.x, y: linkedTextStartCanvas.y + }; + + cornerstoneTools.drawTextBox(context, lesion.lesionName, textCoords.x, textCoords.y, color); + cornerstoneTools.drawTextBox(context, text, textCoords.x, textCoords.y + 20, color); + + //Set measurement text to show lesion table + lesion.measurementText = length.toFixed(2); + + // Lesion Measurement is changed + $(eventData.enabledElement.element).trigger("LesionTextChanged",lesion); + + context.restore(); } + ///////// END IMAGE RENDERING /////// //This function is called from cornerstone-viewport.html and updates lesion measurement and makes the lesion active diff --git a/Packages/lesiontracker/compatibility/measurementManagerDAL.js b/Packages/lesiontracker/compatibility/measurementManagerDAL.js new file mode 100644 index 000000000..4564acfea --- /dev/null +++ b/Packages/lesiontracker/compatibility/measurementManagerDAL.js @@ -0,0 +1,206 @@ +var measurementManagerDAL = (function () { + var trialPatientLocations = []; + var timepoints = []; + + // timepointID = tabId + activeViewportIndex + /*timepoints = [ + { + timepointID: "tp0", + rois: [ + { + UID: "345", + number: 1, + measurement: "22.34", + locationUID: 12345 + }, + { + UID: "245", + number: 2, + measurement: "22.34", + locationUID: 1745 + } + ] + }, + { + timepointID: "tp1", + rois: [ + { + UID: "243", + number: 1, + measurement: "22.34", + locationUID: 12345 + } + ] + }, + { + timepointID: "tp2", + rois: [ + { + UID: "253", + number: 1, + measurement: "0.34", + locationUID: 12345 + } + ] + } + ]; + */ + + // Returns trialPatientLocations array + function getPatientLocations () { + return trialPatientLocations; + } + + function getLocationName (locationUID) { + for(var i = 0; i< trialPatientLocations.length; i++) { + var locationObject = trialPatientLocations[i]; + if(locationObject.uid === locationUID) { + return locationObject.location.location; + } + } + + return ""; + } + + function getTimepoints() { + return timepoints; + } + + // Adds new location to trialPatientLocations array + function addPatientLocation (location) { + var contentId = getContentId(); + var locationUID = uuid.v4(); + var locationObject = {contentId: contentId, uid: locationUID, location: location}; + trialPatientLocations.push(locationObject); + + return locationUID; + } + + + // Insert Measurements Collection + function insertDataToMeasurementCollection (lesionData) { + + + } + + function getContentId () { + return Session.get("activeContentId"); + } + + // Adds new timepoint item to tiemepoints array + function addLesionData (lesionData) { + + // TODO: if find lesionNumber, add + // TODO: Unless create new object + var contentId = getContentId(); + var timepointID = lesionData.timepointID; + var tabMeasurements = Measurements.find({contentId: contentId}).fetch(); + var existingMeasurement; + if(tabMeasurements != undefined && tabMeasurements.length > 0) { + var tabLesionData = tabMeasurements.filter(function(item){return (item.lesionData.lesionNumber == lesionData.lesionNumber);} )[0]; + if(tabLesionData != undefined) { + existingMeasurement = tabLesionData.lesionData; + } + } + + if (existingMeasurement != undefined) { + + var existingTimepoint = existingMeasurement.timepoints; + existingTimepoint[timepointID] = {longestDiameter: lesionData.measurementText}; + + Measurements.update( + { contentId: contentId, "lesionData.lesionNumber": lesionData.lesionNumber}, + { + $set: { + "lesionData.timepoints": existingTimepoint + } + }, {multi: true} + ); + console.log(Measurements.find()) + + } else { + + var timepointArr = {}; + timepointArr[timepointID] = {longestDiameter: lesionData.measurementText}; + var lesionDataCollectionObject = { + lesionNumber: lesionData.lesionNumber, + isTarget: true, + location: getLocationName(lesionData.locationUID), + timepoints: timepointArr + }; + + Measurements.insert({contentId: contentId, lesionData: lesionDataCollectionObject}); + console.log(Measurements.find()); + + } + + // Populate timepoints array + var roi = { + uid: lesionData.uid, + number: lesionData.lesionNumber, + measurement: lesionData.measurementText, + locationUID: lesionData.locationUID + }; + if (timepoints.length) { + timepoints.forEach(function(timepoint) { + if(timepoint.timepointID === timepointID) { + timepoint.rois.push(roi); + } + }); + } else { + timepoints.push({timepointID: timepointID, rois: [roi]}); + } + + insertDataToMeasurementCollection(lesionData); + + } + + // Returns new lesion number according to timepointID + function getNewLesionNumber (timepointID) { + // Check timepoint is in timepoints array + for (var i=0; i< timepoints.length; i++) { + var timepoint = timepoints[i]; + if(timepoint.timepointID === timepointID) { + return timepoint.rois.length + 1; + } + } + + // Add new time point + timepoints.push({timepointID: timepointID, rois: []}); + + return 1; + } + + // If lesion number is added for any timepoint, returns lesion locationUID + function isLesionNumberAdded (lesionNumber) { + + for (var i=0; i< timepoints.length; i++) { + var timepoint = timepoints[i]; + var rois = timepoint.rois; + + for(var j=0; jlesionTableRow }} {{ /each }} + + diff --git a/Packages/lesiontracker/components/lesionTable/lesionTable.js b/Packages/lesiontracker/components/lesionTable/lesionTable.js index 134d04263..165db1cac 100644 --- a/Packages/lesiontracker/components/lesionTable/lesionTable.js +++ b/Packages/lesiontracker/components/lesionTable/lesionTable.js @@ -1,187 +1,52 @@ -measurements = new Meteor.Collection(null); - -var test = { - lesionNumber: 1, - isTarget: true, - location: 'Brain', - timepoints: { - "now": { - imageId: "blah", - timepointUid: "timepointX", - date: 2010, - isDirty: true, - longestDiameter: 5 - }, - "earlier": { - imageId: "blah2", - timepointUid: "timepointy", - date: 2010, - isDirty: true, - longestDiameter: 8 - } - } -}; - -measurements.insert(test); +Measurements = new Meteor.Collection(null); +TimepointNames = new Meteor.Collection(null); Template.lesionTable.helpers({ 'measurement': function() { - return measurements.find(); + var contentId = Session.get("activeContentId"); + console.log(Measurements.find({contentId: contentId})); + return Measurements.find({contentId: contentId}); }, 'timepointNames': function() { - return [ - {name: 'now'}, - {name: 'earlier'} - ]; - } -}); - -/*var lesionTableData; -setLesionTableData = function (data) { - lesionTableData = data; -}; - -getLesionTableData = function () { - return lesionTableData; -}; - -lesionNumberIsAdded = function(data) { - var tabId = data.tabId; - var returnValue = {isFound: false, rowIndex : -1}; - $('#content'+tabId+' table tbody tr td.lesionNumber').each( function(){ - console.log($(this).text()); - var lesionNumber = parseInt($(this).text()); - - if(lesionNumber == data.lesionNumber) { - var $tr = $(this).closest('tr'); - var rowIndex = $tr.index(); - returnValue.rowIndex = rowIndex; - returnValue.isFound = true; - } - }); - - return returnValue; -}; - -returnTblStr = function (obj) { - // Get count of lds - var tabId = obj.tabId; - var lds = $("#content"+tabId).find(".lesionTable th.ld"); - - var rowStr = '' + - '' + - ''+obj.lesionNumber+'' + - 'Y'; - - // Add measurement to right column - if(obj.totalViewportCount) { - for(var i=0; i< lds.length; i++) { - if(i === obj.viewportIndex) { - rowStr += ''+obj.lesionLocationObj.location+''+obj.lesions+''; - - }else{ - rowStr += ''+obj.lesionLocationObj.location+''; - } - } - } - rowStr += ''; - - return rowStr; -}; - -//Link lesionLocationSelected event -$(document).on("lesionLocationSelected",function(event,data ){ - var lesionData = getLesionTableData(); - lesionData.lesionLocationObj = data; - var tabId = lesionData.tabId; - //var el_index = lesionData.viewportIndex; - var tableEl = $("#content"+tabId).find(".lesionTable"); - var tblStr = returnTblStr(lesionData); - $(tableEl).append(tblStr); - -}); - -//Link addLesionToExistedRow event -$(document).on("addLesionToExistedRow",function(event,data ){ - // Get count of lds - var tabId = data.tabId; - var lds = $("#content"+tabId).find(".lesionTable th.ld"); - // Add measurement to right column - for(var i=0; i< lds.length; i++) { - if(i === data.viewportIndex) { - var rowIndex = data.rowIndex + 1; - var row = $("#content"+tabId).find(".lesionTable tr").eq(rowIndex); - var cell = $(row).find("td.lesion").eq(data.viewportIndex); - $(cell).attr("id", data.lineIndex); - $(cell).html(data.lesions); - } - } -}); - -$(document).on("lesionTextChanged", function(event, data){ - var cellId = data.index; - $("td#"+cellId).html(data.measurementText); -}); - - -Template.lesionTable.onRendered( function () { - - // TODO: Set lesion table as hiding-panel - console.log(this); - var template = this; - var tabId = this.data.tabId; - var viewports = $("#content"+tabId).find(".imageViewerViewport"); - var lesionTable = $("#content"+tabId).find(".lesionTable"); - - var viewportCount = viewports.length; - - var lesionTableWidth = $(lesionTable).width(); - var viewportWidth = viewports.width(); - var ldColumnRatio = viewportWidth / lesionTableWidth * 100; - - // Add LD column as viewportCount - // Set lesion table columns width - - if(viewportCount > 0) { - if(viewportCount == 1) { - $('#content'+tabId+' thead tr').append( $('', {text : 'Location', width: ldColumnRatio/2+'%', class:'thLocation'}) ) - $('#content'+tabId+' thead tr').append( $('', {text : 'LD', width: ldColumnRatio/2+'%', class:'ld'}) ) - - } else if(viewportCount == 2) { - - for(var i = 0; i< viewportCount; i++) { - $('#content'+tabId+' thead tr').append( $('', {text : 'Location'+i, width: ldColumnRatio/2+'%', class:'thLocation'}) ) - $('#content'+tabId+' thead tr').append( $('', {text : 'LD'+i, width: ldColumnRatio/2+'%', class:'ld'}) ) - } - - } else if(viewportCount > 2) { - // TODO: Set when viewport count is bigger than 2 - } - } - // TODO: When layout is changed, add and calculate new columns for measurement -}); - -Template.lesionTable.events({ - 'click button.btnRemove': function (e) { - var el = $(e.target); + var contentId = Session.get("activeContentId"); + return Template.instance().timepointNamesDictionary.get(contentId); }, - 'click table tbody tr': function(e) { - console.log(this); - var row = e.currentTarget; - var lesionCells = $(row).find("td.lesion"); - for(var i = 0; i< lesionCells.length; i++) { - var cell = lesionCells[i]; - var idAttr = $(cell).attr("id"); - if(idAttr != undefined) { - // TODO: Create eventObject and trigger LesionToolModified event - var viewports = $(".imageViewerViewport"); - var eventObject = { - enabledElement: cornerstone.getEnabledElement(viewports[0]), - lineIndex: parseInt(idAttr), - type: "active" - }; - $(viewports[0]).trigger("LesionToolModified", eventObject); - } - } + 'lesionData': function() { + var array = []; + var lesions = this.lesionData; + Object.keys(lesions).forEach(function(key) { + array.push(lesions[key]); + }); + return array; } -});*/ \ No newline at end of file +}); + +Template.lesionTable.onRendered(function() { + + // TODO: Create seperate method + var cols = Template.instance().data.viewportColumns.curValue; + var rows = Template.instance().data.viewportRows.curValue; + + var totalViewports = cols * rows; + + var contentId = Session.get('activeContentId'); + for(var i=0; i< totalViewports; i++) { + var timepointNamesArray = []; + if(Template.instance().timepointNamesDictionary.get(contentId) != undefined) { + timepointNamesArray = Template.instance().timepointNamesDictionary.get(contentId); + } + var timepointID = contentId.toString()+ i.toString(); + var timepointName = "Baseline"; + if(i > 0) { + timepointName = "Follow Up "+i; + } + var timepointObject = {id: timepointID, name: timepointName}; + timepointNamesArray.push(timepointObject); + Template.instance().timepointNamesDictionary.set(contentId, timepointNamesArray); + } + +}); + +Template.lesionTable.onCreated(function() { + this.timepointNamesDictionary = new ReactiveDict(); +}); diff --git a/Packages/lesiontracker/components/lesionTable/lesionTable.styl b/Packages/lesiontracker/components/lesionTable/lesionTable.styl index faa910740..bc3007437 100644 --- a/Packages/lesiontracker/components/lesionTable/lesionTable.styl +++ b/Packages/lesiontracker/components/lesionTable/lesionTable.styl @@ -1,6 +1,7 @@ #lesionTableContainer - width: 100% - height: 25% + width: 100% + height: 25% + overflow: auto table.lesionTable thead diff --git a/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.html b/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.html index 682ddab89..73923ee78 100644 --- a/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.html +++ b/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.html @@ -1,11 +1,11 @@ \ No newline at end of file diff --git a/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.js b/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.js index eab82fae2..d7f0c9d37 100644 --- a/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.js +++ b/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.js @@ -1,10 +1,10 @@ Template.lesionTableRow.helpers({ 'timepoints': function() { var array = []; - var timepoints = this.timepoints; + var timepoints = this.lesionData.timepoints; Object.keys(timepoints).forEach(function(key) { array.push(timepoints[key]); }); return array; - }, + } }); diff --git a/Packages/lesiontracker/lib/getActiveTimepointID.js b/Packages/lesiontracker/lib/getActiveTimepointID.js new file mode 100644 index 000000000..b10db86d7 --- /dev/null +++ b/Packages/lesiontracker/lib/getActiveTimepointID.js @@ -0,0 +1,7 @@ +getActiveTimepointID = function (viewportElement) { + var contentId = Session.get("activeContentId"); + var imageViewportElements = $("#"+contentId).find(".imageViewerViewport"); + var index = $(imageViewportElements).index(viewportElement); + + return contentId.toString() + index.toString(); +}; \ No newline at end of file diff --git a/Packages/lesiontracker/lib/uuid.js b/Packages/lesiontracker/lib/uuid.js new file mode 100755 index 000000000..0b596fc3e --- /dev/null +++ b/Packages/lesiontracker/lib/uuid.js @@ -0,0 +1,250 @@ +// uuid.js +// +// Copyright (c) 2010-2012 Robert Kieffer +// MIT License - http://opensource.org/licenses/mit-license.php + +(function() { + var _global = this; + + // Unique ID creation requires a high quality random # generator. We feature + // detect to determine the best RNG source, normalizing to a function that + // returns 128-bits of randomness, since that's what's usually required + var _rng; + + // Allow for MSIE11 msCrypto + var _crypto = _global.crypto || _global.msCrypto; + + // Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html + // + // Moderately fast, high quality + if (typeof(_global.require) == 'function') { + try { + var _rb = _global.require('crypto').randomBytes; + _rng = _rb && function() {return _rb(16);}; + } catch(e) {} + } + + if (!_rng && _crypto && _crypto.getRandomValues) { + // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto + // + // Moderately fast, high quality + var _rnds8 = new Uint8Array(16); + _rng = function whatwgRNG() { + _crypto.getRandomValues(_rnds8); + return _rnds8; + }; + } + + if (!_rng) { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var _rnds = new Array(16); + _rng = function() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return _rnds; + }; + } + + // Buffer class to use + var BufferClass = typeof(_global.Buffer) == 'function' ? _global.Buffer : Array; + + // Maps for number <-> hex string conversion + var _byteToHex = []; + var _hexToByte = {}; + for (var i = 0; i < 256; i++) { + _byteToHex[i] = (i + 0x100).toString(16).substr(1); + _hexToByte[_byteToHex[i]] = i; + } + + // **`parse()` - Parse a UUID into it's component bytes** + function parse(s, buf, offset) { + var i = (buf && offset) || 0, ii = 0; + + buf = buf || []; + s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { + if (ii < 16) { // Don't overflow! + buf[i + ii++] = _hexToByte[oct]; + } + }); + + // Zero out remaining bytes if string was short + while (ii < 16) { + buf[i + ii++] = 0; + } + + return buf; + } + + // **`unparse()` - Convert UUID byte array (ala parse()) into a string** + function unparse(buf, offset) { + var i = offset || 0, bth = _byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; + } + + // **`v1()` - Generate time-based UUID** + // + // Inspired by https://github.com/LiosK/UUID.js + // and http://docs.python.org/library/uuid.html + + // random #'s we need to init node and clockseq + var _seedBytes = _rng(); + + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + var _nodeId = [ + _seedBytes[0] | 0x01, + _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] + ]; + + // Per 4.2.2, randomize (14 bit) clockseq + var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; + + // Previous uuid creation time + var _lastMSecs = 0, _lastNSecs = 0; + + // See https://github.com/broofa/node-uuid for API details + function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + + var clockseq = options.clockseq != null ? options.clockseq : _clockseq; + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs != null ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq == null) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + var node = options.node || _nodeId; + for (var n = 0; n < 6; n++) { + b[i + n] = node[n]; + } + + return buf ? buf : unparse(b); + } + + // **`v4()` - Generate random UUID** + + // See https://github.com/broofa/node-uuid for API details + function v4(options, buf, offset) { + // Deprecated - 'format' argument, as supported in v1.2 + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options == 'binary' ? new BufferClass(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || _rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ii++) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || unparse(rnds); + } + + // Export public API + var uuid = v4; + uuid.v1 = v1; + uuid.v4 = v4; + uuid.parse = parse; + uuid.unparse = unparse; + uuid.BufferClass = BufferClass; + + if (typeof(module) != 'undefined' && module.exports) { + // Publish as node.js module + module.exports = uuid; + } else if (typeof define === 'function' && define.amd) { + // Publish as AMD module + define(function() {return uuid;}); + + + } else { + // Publish as global (in browsers) + var _previousRoot = _global.uuid; + + // **`noConflict()` - (browser only) to reset global 'uuid' var** + uuid.noConflict = function() { + _global.uuid = _previousRoot; + return uuid; + }; + + _global.uuid = uuid; + } +}).call(this); diff --git a/Packages/lesiontracker/package.js b/Packages/lesiontracker/package.js index c4ed6f673..420ee6338 100644 --- a/Packages/lesiontracker/package.js +++ b/Packages/lesiontracker/package.js @@ -15,6 +15,7 @@ Package.onUse(function (api) { api.use('cornerstone'); api.addFiles('compatibility/lesionTool.js', 'client', {bare: true}); + api.addFiles('compatibility/measurementManagerDAL.js', 'client', {bare: true}); api.addFiles('components/lesionDialog/lesionDialog.html', 'client'); api.addFiles('components/lesionDialog/lesionDialog.js', 'client'); @@ -32,4 +33,9 @@ Package.onUse(function (api) { api.addFiles('components/lesionTableTimepointCell/lesionTableTimepointCell.html', 'client'); api.addFiles('components/lesionTableTimepointHeader/lesionTableTimepointHeader.html', 'client'); + + // Library functions + api.addFiles('lib/getActiveTimepointID.js', 'client'); + api.addFiles('lib/uuid.js', 'client'); + }); \ No newline at end of file diff --git a/Packages/viewerbase/components/viewer/imageViewerViewport/imageViewerViewport.js b/Packages/viewerbase/components/viewer/imageViewerViewport/imageViewerViewport.js index fd722f35f..cc8653e6d 100644 --- a/Packages/viewerbase/components/viewer/imageViewerViewport/imageViewerViewport.js +++ b/Packages/viewerbase/components/viewer/imageViewerViewport/imageViewerViewport.js @@ -255,6 +255,7 @@ Template.imageViewerViewport.events({ if (this.viewportIndex === this.activeViewport.curValue) { return; } + Session.set("ActivateViewportIndex", this.viewportIndex); console.log('ActivateViewport index: ' + this.viewportIndex); this.activeViewport.curValue = this.viewportIndex; enablePrefetchOnElement(this.viewportIndex); diff --git a/Packages/worklist/components/worklist.js b/Packages/worklist/components/worklist.js index 097a9ea7a..086f7bd72 100644 --- a/Packages/worklist/components/worklist.js +++ b/Packages/worklist/components/worklist.js @@ -18,6 +18,10 @@ switchToTab = function(contentId) { var data = ViewerData[contentId]; console.log("Switching to tab: " + contentId); + + // Set active tab + Session.set("activeContentId", contentId); + $('.tabTitle a[data-target="#' + contentId + '"]').tab('show'); $("#viewer").remove(); @@ -70,6 +74,7 @@ Template.worklist.onRendered(function() { }; Session.set('ViewerData', ViewerData); + switchToTab(contentId); }); }); \ No newline at end of file diff --git a/Packages/worklist/lib/generateUUID.js b/Packages/worklist/lib/generateUUID.js index a03d70e59..3de8a8a46 100644 --- a/Packages/worklist/lib/generateUUID.js +++ b/Packages/worklist/lib/generateUUID.js @@ -7,4 +7,4 @@ generateUUID = function() { return(c=='x' ? r :(r&0x3|0x8)).toString(8); }); return uuid; -}; \ No newline at end of file +};