Update cornerstoneTools to allow some handles off-screen. Add hardcoded MG hanging protocol to window manager. Fix tooltips in toolbar buttons

This commit is contained in:
Erik Ziegler 2015-11-24 18:08:00 +01:00
parent e6fd2e60b0
commit ec9b77c4d1
5 changed files with 318 additions and 25 deletions

View File

@ -5,7 +5,7 @@ Object.keys(ViewerData).forEach(function(contentId) {
var tabData = ViewerData[contentId];
var data = {
title: tabData.title,
contentid: tabData.contentid,
contentid: tabData.contentid
};
WorklistTabs.insert(data);
});
@ -27,8 +27,6 @@ Router.route('/viewer/:_id', {
layoutTemplate: 'layout',
name: 'viewer',
onBeforeAction: function() {
log.info('Router GetStudyMetadata');
var studyInstanceUid = this.params._id;
// Check if this study is already loaded in a tab

View File

@ -1,4 +1,4 @@
/*! cornerstoneTools - v0.7.7 - 2015-11-22 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstoneTools */
/*! cornerstoneTools - v0.7.7 - 2015-11-23 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstoneTools */
// Begin Source: src/header.js
if (typeof cornerstone === 'undefined') {
cornerstone = {};
@ -6078,6 +6078,10 @@ if (typeof cornerstoneTools === 'undefined') {
Object.keys(handles).forEach(function(name) {
var handle = handles[name];
if (handle.allowedOutsideImage === true) {
return;
}
if (cornerstoneMath.point.insideRect(handle, imageRect) === false) {
handleOutsideImage = true;
}

View File

@ -26,11 +26,6 @@ Template.imageViewerViewports.helpers({
viewportColumns = ViewerData[contentId].viewportColumns;
}
// Update viewerData
ViewerData[contentId].viewportRows = viewportRows;
ViewerData[contentId].viewportColumns = viewportColumns;
Session.set("ViewerData", ViewerData);
var viewportData;
if (!$.isEmptyObject(ViewerData[contentId].loadedSeriesData)) {
viewportData = ViewerData[contentId].loadedSeriesData;
@ -44,9 +39,19 @@ Template.imageViewerViewports.helpers({
inputData.DisplaySetPresentationGroup = Session.get('WindowManagerPresentationGroup');
var hangingProtocolViewportData = WindowManager.getHangingProtocol(inputData);
if (Session.get('UseHangingProtocol')) {
viewportData = hangingProtocolViewportData;
viewportData = hangingProtocolViewportData.viewports;
viewportRows = hangingProtocolViewportData.viewportRows || viewportRows;
viewportColumns = hangingProtocolViewportData.viewportColumns || viewportColumns;
}
// Update viewerData
ViewerData[contentId].viewportRows = viewportRows;
ViewerData[contentId].viewportColumns = viewportColumns;
Session.set("ViewerData", ViewerData);
this.viewportRows = viewportRows;
this.viewportColumns = viewportColumns;
var numViewports = viewportRows * viewportColumns;
for (var i=0; i < numViewports; ++i) {
var data = {
@ -57,16 +62,16 @@ Template.imageViewerViewports.helpers({
viewportRows: viewportRows
};
if (viewportData && viewportData[i]) {
if (viewportData && !$.isEmptyObject(viewportData[i])) {
data.seriesInstanceUid = viewportData[i].seriesInstanceUid;
data.studyInstanceUid = viewportData[i].studyInstanceUid;
data.currentImageIdIndex = viewportData[i].currentImageIdIndex;
data.viewport = viewportData[i].viewport;
} else if (hangingProtocolViewportData && hangingProtocolViewportData[i]) {
data.seriesInstanceUid = hangingProtocolViewportData[i].seriesInstanceUid;
data.studyInstanceUid = hangingProtocolViewportData[i].studyInstanceUid;
data.currentImageIdIndex = hangingProtocolViewportData[i].currentImageIdIndex;
data.viewport = hangingProtocolViewportData[i].viewport;
} else if (hangingProtocolViewportData && !$.isEmptyObject(hangingProtocolViewportData.viewports[i])) {
data.seriesInstanceUid = hangingProtocolViewportData.viewports[i].seriesInstanceUid;
data.studyInstanceUid = hangingProtocolViewportData.viewports[i].studyInstanceUid;
data.currentImageIdIndex = hangingProtocolViewportData.viewports[i].currentImageIdIndex;
data.viewport = hangingProtocolViewportData.viewports[i].viewport;
}
ViewerWindows.insert(data);

View File

@ -110,6 +110,8 @@ function getDefaultButtonData() {
Template.toolbar.events({
'click .imageViewerTool': function(e) {
$(e.currentTarget).tooltip('hide');
var tool = e.currentTarget.id;
console.log('Setting active tool to: ' + tool);
@ -117,6 +119,8 @@ Template.toolbar.events({
toolManager.setActiveTool(tool, elements);
},
'click .imageViewerCommand': function(e) {
$(e.currentTarget).tooltip('hide');
var command = e.currentTarget.id;
if (!OHIF.viewer.functionList.hasOwnProperty(command)) {
return;

View File

@ -1,3 +1,243 @@
/**
* This is a temporary function which will return a hardcoded hanging protocol as a JavaScript object
*/
function getMammoHangingProtocolObject() {
var protocol = [{
stage: 1,
rows: 2,
columns: 4,
viewports: [{
seriesDescription: 'RCC',
study: 'prior'
}, {
seriesDescription: 'LCC',
study: 'prior'
}, {
seriesDescription: 'RMLO',
study: 'prior'
}, {
seriesDescription: 'LMLO',
study: 'prior'
}, {
seriesDescription: 'RCC',
study: 'current'
}, {
seriesDescription: 'LCC',
study: 'current'
}, {
seriesDescription: 'RMLO',
study: 'current'
}, {
seriesDescription: 'LMLO',
study: 'current'
}
]
}, {
stage: 2,
rows: 1,
columns: 2,
viewports: [{
seriesDescription: 'RCC',
study: 'current'
}, {
seriesDescription: 'LCC',
study: 'current'
}
]
}, {
stage: 3,
rows: 1,
columns: 2,
viewports: [{
seriesDescription: 'RMLO',
study: 'current'
}, {
seriesDescription: 'LMLO',
study: 'current'
}
]
}, {
stage: 4,
rows: 1,
columns: 2,
viewports: [{
seriesDescription: 'RCC',
study: 'current'
}, {
seriesDescription: 'RCC',
study: 'prior'
}
]
}, {
stage: 5,
rows: 1,
columns: 2,
viewports: [{
seriesDescription: 'LCC',
study: 'current'
}, {
seriesDescription: 'LCC',
study: 'prior'
}
]
}, {
stage: 6,
rows: 1,
columns: 2,
viewports: [{
seriesDescription: 'LMLO',
study: 'current'
}, {
seriesDescription: 'LMLO',
study: 'prior'
}
]
}, {
stage: 7,
rows: 1,
columns: 2,
viewports: [{
seriesDescription: 'RMLO',
study: 'current'
}, {
seriesDescription: 'RMLO',
study: 'prior'
}
]
}, {
stage: 8,
rows: 2,
columns: 4,
viewports: [{
seriesDescription: 'RCC',
study: 'prior',
options: {
includeCADMarkers: true
}
}, {
seriesDescription: 'LCC',
study: 'prior',
options: {
includeCADMarkers: true
}
}, {
seriesDescription: 'RMLO',
study: 'prior',
options: {
includeCADMarkers: true
}
}, {
seriesDescription: 'LMLO',
study: 'prior',
options: {
includeCADMarkers: true
}
}, {
seriesDescription: 'RCC',
study: 'current',
options: {
includeCADMarkers: true
}
}, {
seriesDescription: 'LCC',
study: 'current',
options: {
includeCADMarkers: true
}
}, {
seriesDescription: 'RMLO',
study: 'current',
options: {
includeCADMarkers: true
}
}, {
seriesDescription: 'LMLO',
study: 'current',
options: {
includeCADMarkers: true
}
}
]
}
];
return protocol;
}
function findSeriesByDescription(seriesDescription, study) {
var seriesInstanceUid;
study.seriesList.forEach(function(series) {
if (!series.seriesDescription) {
return;
}
var currentSeriesDescription = series.seriesDescription.replace(' ', '');
if (currentSeriesDescription === seriesDescription) {
seriesInstanceUid = series.seriesInstanceUid;
return false;
}
});
return seriesInstanceUid;
}
/**
* (Work in progress) Uses the information from a DICOM Hanging Protocol
* to identify and display studies and series in the image viewer
*
* @param hangingProtocol
* @param inputData
* @returns {Array} Array of viewport data to be displayed
*/
function applyHangingProtocol(hangingProtocol, inputData) {
var presentationGroup = inputData.DisplaySetPresentationGroup || 1;
var studies = ViewerStudies;
var currentProtocolData = hangingProtocol[presentationGroup - 1];
var viewportData = {
viewports: [],
viewportRows: currentProtocolData.rows,
viewportColumns: currentProtocolData.columns
};
var currentStudy = ViewerStudies.find({}, {$sort: {studyDate: 1}}).fetch()[0];
var otherStudies = WorklistStudies.find({
patientId: currentStudy.patientId,
studyInstanceUid: {
$ne: currentStudy.studyInstanceUid
}
}, {$sort: {
studyDate: 1
}}).fetch();
var priorStudy = otherStudies[0];
currentProtocolData.viewports.forEach(function(viewport, index) {
if (viewport.study === 'current') {
study = currentStudy;
} else if (viewport.study === 'prior') {
study = currentStudy;
/*ViewerStudies.find({
studyInstanceUid: {
$ne: currentStudy.studyInstanceUid
}
}, {$sort: {studyDate: 1}}).fetch()[0];*/
}
seriesInstanceUid = findSeriesByDescription(viewport.seriesDescription, study);
viewportData.viewports[index] = {
seriesInstanceUid: seriesInstanceUid,
studyInstanceUid: study.studyInstanceUid,
currentImageIdIndex: 0,
options: viewport.options
};
});
return viewportData;
}
/**
* This is a temporary function which will return a hardcoded hanging protocol as a JavaScript object
* The purpose of this is to act as a stub until we are actually parsing DICOM Hanging Protocol files,
@ -61,7 +301,7 @@ function getMammoHangingProtocol() {
{
ImageSetNumber: 2,
ImageSetSelectorCategory: 'ABSTRACT_PRIOR',
AbstractPriorValue: '1\1',
AbstractPriorValue: '1\\1',
ImageSetLabel: 'Prior MG Breast'
}]
}],
@ -103,7 +343,6 @@ function getMammoHangingProtocol() {
FilterByOperator: 'MEMBER_OF'
}]
},
// Stage 3
{
// Left side image (R MLO Current)
ImageSetNumber: 1,
@ -143,6 +382,39 @@ function getMammoHangingProtocol() {
FilterByCategory: 'SERIES_DESCRIPTION',
FilterByOperator: 'MEMBER_OF'
}]
}, {
// Testing purposes
// Left side image (R MLO Current)
ImageSetNumber: 1,
DisplaySetNumber: 1,
DisplaySetPresentationGroup: 3,
DisplaySetPresentationGroupDescription: 'Current Mediolateral only',
ImageBoxesSequence: [{
DisplayEnvironmentSpatialPosition: '0\0.2\0.16667\0',
ImageBoxNumber: 1,
ImageBoxLayoutType: 'STACK'
}],
FilterOperationsSequence: [{
SelectorAttributeVR: 'CS',
SelectorCSValue: 'R MLO',
FilterByCategory: 'SERIES_DESCRIPTION',
FilterByOperator: 'MEMBER_OF'
}]
}, {
// Right side image (R CC Current)
ImageSetNumber: 1,
DisplaySetNumber: 1,
DisplaySetPresentationGroup: 3,
ImageBoxesSequence: [{
ImageBoxNumber: 1,
ImageBoxLayoutType: 'STACK'
}],
FilterOperationsSequence: [{
SelectorAttributeVR: 'CS',
SelectorCSValue: 'R CC',
FilterByCategory: 'SERIES_DESCRIPTION',
FilterByOperator: 'MEMBER_OF'
}]
}],
PartialDataDisplayHandling: 'MAINTAIN_LAYOUT',
SynchronizedScrollingSequence: [],
@ -215,7 +487,10 @@ function applyDICOMHangingProtocol(hangingProtocol, inputData) {
var studies = ViewerStudies;
var currentDisplaySets = findSetsByPresentationGroup(hangingProtocol.DisplaySetsSequence, presentationGroup);
var viewportData = [];
var viewportData = {
viewports: []
};
currentDisplaySets.forEach(function(displaySet, index) {
// TODO= Find study information by image set properties and
// image set number of this display set
@ -226,7 +501,7 @@ function applyDICOMHangingProtocol(hangingProtocol, inputData) {
var study = ViewerStudies.findOne({studyInstanceUid: studyInstanceUid});
seriesInstanceUid = findSeries(displaySet, study);
viewportData[index] = {
viewportData.viewports[index] = {
seriesInstanceUid: seriesInstanceUid,
studyInstanceUid: studyInstanceUid,
currentImageIdIndex: 0
@ -272,7 +547,9 @@ function defaultHangingProtocol(inputData) {
});
});
var viewportData = [];
var viewportData = {
viewports: []
};
var numViewports = viewportRows * viewportColumns;
for (var i=0; i < numViewports; ++i) {
@ -280,7 +557,7 @@ function defaultHangingProtocol(inputData) {
// We don't have enough stacks to fill the desired number of viewports, so stop here
break;
}
viewportData[i] = {
viewportData.viewports[i] = {
seriesInstanceUid: stacks[i].series.seriesInstanceUid,
studyInstanceUid: stacks[i].study.studyInstanceUid,
currentImageIdIndex: 0
@ -312,9 +589,14 @@ function getHangingProtocol(inputData) {
});
if (modalities.indexOf('MG') > -1) {
var hangingProtocol = getMammoHangingProtocol();
var hp = getMammoHangingProtocolObject();
Session.set('WindowManagerPresentationGroup', presentationGroup);
return applyDICOMHangingProtocol(hangingProtocol, inputData);
var testData = applyHangingProtocol(hp, inputData);
return testData;
// Commenting this out for now so we can hardcode a MG protocol
/*var hangingProtocol = getMammoHangingProtocol();
Session.set('WindowManagerPresentationGroup', presentationGroup);
return applyDICOMHangingProtocol(hangingProtocol, inputData);*/
}
Session.set('WindowManagerPresentationGroup', undefined);
@ -349,7 +631,7 @@ function getNumPresentationGroups() {
// TODO=Pull this information from the largest
// value of DisplaySetPresentationGroup in the DisplaySetsSequence
// after the DICOM-HP is parsed
return 2;
return 8;
}
function getCurrentPresentationGroup() {