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:
parent
e6fd2e60b0
commit
ec9b77c4d1
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user