diff --git a/LesionTracker/client/components/viewer.js b/LesionTracker/client/components/viewer.js index 6d337bf6b..94f5e26f6 100644 --- a/LesionTracker/client/components/viewer.js +++ b/LesionTracker/client/components/viewer.js @@ -48,6 +48,12 @@ Template.viewer.onCreated(function() { } OHIF.viewer.isPlaying[viewportIndex] = !OHIF.viewer.isPlaying[viewportIndex]; Session.set('UpdateCINE', Random.id()); + }, + previousPresentationGroup: function() { + WindowManager.previousPresentationGroup(); + }, + nextPresentationGroup: function() { + WindowManager.nextPresentationGroup(); } }; diff --git a/OHIFViewer/client/components/viewer/viewer.js b/OHIFViewer/client/components/viewer/viewer.js index e92042de0..a560a42f3 100644 --- a/OHIFViewer/client/components/viewer/viewer.js +++ b/OHIFViewer/client/components/viewer/viewer.js @@ -52,6 +52,12 @@ Template.viewer.onCreated(function() { } OHIF.viewer.isPlaying[viewportIndex] = !OHIF.viewer.isPlaying[viewportIndex]; Session.set('UpdateCINE', Random.id()); + }, + previousPresentationGroup: function() { + WindowManager.previousPresentationGroup(); + }, + nextPresentationGroup: function() { + WindowManager.nextPresentationGroup(); } }; diff --git a/Packages/viewerbase/components/studyBrowser/thumbnailEntry/thumbnailEntry.js b/Packages/viewerbase/components/studyBrowser/thumbnailEntry/thumbnailEntry.js index 52927b6ad..e31114647 100644 --- a/Packages/viewerbase/components/studyBrowser/thumbnailEntry/thumbnailEntry.js +++ b/Packages/viewerbase/components/studyBrowser/thumbnailEntry/thumbnailEntry.js @@ -186,6 +186,7 @@ function thumbnailDragEndHandler(e, target) { // Rerender the viewport using the drag and drop data rerenderViewportWithNewSeries(element, OHIF.viewer.dragAndDropData); + Session.get('UseHangingProtocol', false); return false; } diff --git a/Packages/viewerbase/components/viewer/hangingProtocolButtons/hangingProtocolButtons.html b/Packages/viewerbase/components/viewer/hangingProtocolButtons/hangingProtocolButtons.html new file mode 100644 index 000000000..3c243fb05 --- /dev/null +++ b/Packages/viewerbase/components/viewer/hangingProtocolButtons/hangingProtocolButtons.html @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/Packages/viewerbase/components/viewer/hangingProtocolButtons/hangingProtocolButtons.js b/Packages/viewerbase/components/viewer/hangingProtocolButtons/hangingProtocolButtons.js new file mode 100644 index 000000000..f306d162d --- /dev/null +++ b/Packages/viewerbase/components/viewer/hangingProtocolButtons/hangingProtocolButtons.js @@ -0,0 +1,11 @@ +Template.hangingProtocolButtons.helpers({ + 'isNextAvailable': function() { + var presentationGroup = Session.get('WindowManagerPresentationGroup'); + var numPresentationGroups = WindowManager.getNumPresentationGroups(); + return presentationGroup < numPresentationGroups; + }, + 'isPreviousAvailable': function() { + var presentationGroup = Session.get('WindowManagerPresentationGroup'); + return presentationGroup > 1; + } +}); \ No newline at end of file diff --git a/Packages/viewerbase/components/viewer/imageViewerViewports/imageViewerViewports.js b/Packages/viewerbase/components/viewer/imageViewerViewports/imageViewerViewports.js index 80e074f01..10b556f43 100644 --- a/Packages/viewerbase/components/viewer/imageViewerViewports/imageViewerViewports.js +++ b/Packages/viewerbase/components/viewer/imageViewerViewports/imageViewerViewports.js @@ -41,7 +41,11 @@ Template.imageViewerViewports.helpers({ viewportRows: viewportRows }; + inputData.DisplaySetPresentationGroup = Session.get('WindowManagerPresentationGroup'); var hangingProtocolViewportData = WindowManager.getHangingProtocol(inputData); + if (Session.get('UseHangingProtocol')) { + viewportData = hangingProtocolViewportData; + } var numViewports = viewportRows * viewportColumns; for (var i=0; i < numViewports; ++i) { diff --git a/Packages/viewerbase/components/viewer/toolbar/toolbar.html b/Packages/viewerbase/components/viewer/toolbar/toolbar.html index b4616916a..e9f084cbf 100644 --- a/Packages/viewerbase/components/viewer/toolbar/toolbar.html +++ b/Packages/viewerbase/components/viewer/toolbar/toolbar.html @@ -12,6 +12,10 @@ {{ #if includeLayoutButton }} {{ >layoutButton }} {{ /if }} + + {{ #if includeHangingProtocolButtons }} + {{ >hangingProtocolButtons }} + {{ /if }} \ No newline at end of file diff --git a/Packages/viewerbase/components/viewer/toolbar/toolbar.js b/Packages/viewerbase/components/viewer/toolbar/toolbar.js index 00c8faba9..36bd50314 100644 --- a/Packages/viewerbase/components/viewer/toolbar/toolbar.js +++ b/Packages/viewerbase/components/viewer/toolbar/toolbar.js @@ -152,5 +152,11 @@ Template.toolbar.helpers({ return this.toolbarOptions.includeLayoutButton; } return true; + }, + 'includeHangingProtocolButtons': function() { + if (this.toolbarOptions && this.toolbarOptions.includeHangingProtocolButtons !== undefined) { + return this.toolbarOptions.includeHangingProtocolButtons; + } + return true; } }); \ No newline at end of file diff --git a/Packages/viewerbase/lib/metaDataProvider.js b/Packages/viewerbase/lib/metaDataProvider.js index ed792d161..0d191a302 100644 --- a/Packages/viewerbase/lib/metaDataProvider.js +++ b/Packages/viewerbase/lib/metaDataProvider.js @@ -44,6 +44,8 @@ addMetaData = function(imageId, data) { sopInstanceUid: instanceMetaData.sopInstanceUid, sopClassUid: instanceMetaData.sopClassUid, instanceNumber: instanceMetaData.instanceNumber, + laterality: instanceMetaData.laterality, + viewPosition: instanceMetaData.viewPosition, index: imageIndex }; diff --git a/Packages/viewerbase/lib/windowManager.js b/Packages/viewerbase/lib/windowManager.js index fb9e17219..181591eb5 100644 --- a/Packages/viewerbase/lib/windowManager.js +++ b/Packages/viewerbase/lib/windowManager.js @@ -69,7 +69,8 @@ function getMammoHangingProtocol() { // Skip Nominal Screen Definition Sequence for now, // http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.23.3.html - DisplaySetsSequence: [{ + DisplaySetsSequence: [ + { // Left side image (R MLO Current) ImageSetNumber: 1, DisplaySetNumber: 1, @@ -80,6 +81,38 @@ function getMammoHangingProtocol() { ImageBoxNumber: 1, ImageBoxLayoutType: 'STACK' }], + FilterOperationsSequence: [{ + SelectorAttributeVR: 'CS', + SelectorCSValue: 'R CC', + FilterByCategory: 'SERIES_DESCRIPTION', + FilterByOperator: 'MEMBER_OF' + }], + }, { + // Right side image (L MLO Current) + ImageSetNumber: 1, + DisplaySetNumber: 1, + DisplaySetPresentationGroup: 1, + ImageBoxesSequence: [{ + ImageBoxNumber: 1, + ImageBoxLayoutType: 'STACK' + }], + FilterOperationsSequence: [{ + SelectorAttributeVR: 'CS', + SelectorCSValue: 'L CC', + FilterByCategory: 'SERIES_DESCRIPTION', + FilterByOperator: 'MEMBER_OF' + }] + }, { + // Left side image (R MLO Current) + ImageSetNumber: 1, + DisplaySetNumber: 1, + DisplaySetPresentationGroup: 2, + DisplaySetPresentationGroupDescription: 'Current Mediolateral only', + ImageBoxesSequence: [{ + DisplayEnvironmentSpatialPosition: '0\0.2\0.16667\0', + ImageBoxNumber: 1, + ImageBoxLayoutType: 'STACK' + }], FilterOperationsSequence: [{ SelectorAttributeVR: 'CS', SelectorCSValue: 'R MLO', @@ -97,7 +130,7 @@ function getMammoHangingProtocol() { // Right side image (L MLO Current) ImageSetNumber: 1, DisplaySetNumber: 1, - DisplaySetPresentationGroup: 1, + DisplaySetPresentationGroup: 2, ImageBoxesSequence: [{ ImageBoxNumber: 1, ImageBoxLayoutType: 'STACK' @@ -254,8 +287,8 @@ function defaultHangingProtocol(inputData) { return viewportData; } -var currentStage = 0; var hangingProtocol; +var presentationGroup = 1; function getHangingProtocol(inputData) { // TODO = Update this to use Collection logic @@ -278,9 +311,11 @@ function getHangingProtocol(inputData) { if (modalities.indexOf('MG') > -1) { var hangingProtocol = getMammoHangingProtocol(); + Session.set('WindowManagerPresentationGroup', presentationGroup); return applyDICOMHangingProtocol(hangingProtocol, inputData); } + Session.set('WindowManagerPresentationGroup', undefined); return defaultHangingProtocol(inputData); } @@ -288,9 +323,50 @@ function setHangingProtocol(protocol) { hangingProtocol = protocol; } +function previousPresentationGroup() { + presentationGroup--; + presentationGroup = Math.max(1, presentationGroup); + + log.info('previousPresentationGroup: ' + presentationGroup); + Session.set('WindowManagerPresentationGroup', presentationGroup); + Session.set('UseHangingProtocol', Random.id()); +} + +function nextPresentationGroup() { + var numPresentationGroups = getNumPresentationGroups(); + + presentationGroup++; + presentationGroup = Math.min(numPresentationGroups, presentationGroup); + + log.info('nextPresentationGroup: ' + presentationGroup); + Session.set('WindowManagerPresentationGroup', presentationGroup); + Session.set('UseHangingProtocol', Random.id()); +} + +function getNumPresentationGroups() { + // TODO=Pull this information from the largest + // value of DisplaySetPresentationGroup in the DisplaySetsSequence + // after the DICOM-HP is parsed + return 2; +} + +function getCurrentPresentationGroup() { + return presentationGroup; +} + +function setCurrentPresentationGroup(groupNumber) { + // Unused for now + presentationGroup = groupNumber; +} + WindowManager = { setHangingProtocol: setHangingProtocol, - getHangingProtocol: getHangingProtocol + getHangingProtocol: getHangingProtocol, + getNumPresentationGroups: getNumPresentationGroups, + setCurrentPresentationGroup: setCurrentPresentationGroup, + getCurrentPresentationGroup: getCurrentPresentationGroup, + nextPresentationGroup: nextPresentationGroup, + previousPresentationGroup: previousPresentationGroup }; WindowManager.setHangingProtocol(defaultHangingProtocol); diff --git a/Packages/viewerbase/log.js b/Packages/viewerbase/log.js index e188235f2..bb7ba9220 100644 --- a/Packages/viewerbase/log.js +++ b/Packages/viewerbase/log.js @@ -1,3 +1,3 @@ // Create package logger using loglevel // https://atmospherejs.com/spacejamio/loglevel -log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'warn'); \ No newline at end of file +log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'info'); \ No newline at end of file diff --git a/Packages/viewerbase/package.js b/Packages/viewerbase/package.js index 0185e8660..0cbb3e346 100644 --- a/Packages/viewerbase/package.js +++ b/Packages/viewerbase/package.js @@ -86,6 +86,9 @@ Package.onUse(function (api) { api.addFiles('components/viewer/playClipButton/playClipButton.html', 'client'); api.addFiles('components/viewer/playClipButton/playClipButton.js', 'client'); + api.addFiles('components/viewer/hangingProtocolButtons/hangingProtocolButtons.html', 'client'); + api.addFiles('components/viewer/hangingProtocolButtons/hangingProtocolButtons.js', 'client'); + api.addFiles('components/viewer/layoutButton/layoutButton.html', 'client'); api.addFiles('components/viewer/toolbar/toolbar.html', 'client'); diff --git a/Packages/viewerbase/server/services/wado/retrieveMetadata.js b/Packages/viewerbase/server/services/wado/retrieveMetadata.js index 9f6734003..6ffc415f5 100644 --- a/Packages/viewerbase/server/services/wado/retrieveMetadata.js +++ b/Packages/viewerbase/server/services/wado/retrieveMetadata.js @@ -101,7 +101,9 @@ function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { windowWidth: DICOMWeb.getString(instance['00281051']), rescaleIntercept: DICOMWeb.getNumber(instance['00281052']), rescaleSlope: DICOMWeb.getNumber(instance['00281053']), - sourceImageInstanceUid: getSourceImageInstanceUid(instance) + sourceImageInstanceUid: getSourceImageInstanceUid(instance), + laterality: DICOMWeb.getString(instance['00200062']), + viewPosition: DICOMWeb.getString(instance['00185101']), }; if (server.imageRendering === 'wadouri') {