diff --git a/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.html b/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.html index d45ac6c16..3a6f9fd49 100644 --- a/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.html +++ b/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.html @@ -18,25 +18,22 @@
{{seriesDescription}}
{{studyInfo 'AccessionNumber'}}
{{formatDA (studyInfo 'AcquisitionDate')}} {{formatTM (studyInfo 'AcquisitionTime')}}
-
{{#if seriesNumber}}S: {{seriesNumber}}{{#if gt numImages 1}},{{/if}}{{/if}} {{#if gt numImages 1}}I: {{instanceNumber}} ({{imageIndex}}/{{numImages}}){{/if}}
+
{{#if seriesNumber}}S: {{seriesNumber}}{{#if gt numImages 1}},{{/if}} {{/if}}{{#if gt instanceNumber 0}}I: {{instanceNumber}} {{/if}}{{#if gt numImages 1}}({{imageIndex}}/{{numImages}}){{/if}}
{{timepointName}}
-
{{#if zoom}}Zoom: {{formatNumberPrecision zoom 0}}%{{/if}}
-
{{compression}}
-
{{wwwc}}
+
{{studyInfo 'StationName'}}
+
{{studyInfo 'ManufacturersModelName'}}
+
{{studyInfo 'InstitutionName'}}
-
{{#if seriesNumber}}Ser: {{seriesNumber}}{{/if}}
-
{{#if gt numImages 1}}Img: {{instanceNumber}} ({{imageIndex}}/{{numImages}}){{/if}}
-
{{#if frameRate}}{{formatNumberPrecision frameRate 2}} FPS{{/if}}
-
{{imageDimensions}}
{{#if location}}Loc: {{formatNumberPrecision location 2}} mm{{/if}} {{#if thickness}}Thick: {{formatNumberPrecision thickness 2}} mm{{/if}} {{#if spacingBetweenSlices}}Spacing: {{formatNumberPrecision spacingBetweenSlices 2}} mm{{/if}}
-
{{seriesDescription}}
+
{{#if zoom}}Zoom: {{formatNumberPrecision zoom 2}}x{{/if}}
+
{{wwwc}}
{{/unless}} diff --git a/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.js b/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.js index 03530fe02..d19e7d09d 100644 --- a/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.js +++ b/Packages/ohif-measurements/client/components/longitudinal/longitudinalViewportOverlay/longitudinalViewportOverlay.js @@ -2,7 +2,10 @@ import { Template } from 'meteor/templating'; import { Session } from 'meteor/session'; import { Tracker } from 'meteor/tracker'; import { ReactiveVar } from 'meteor/reactive-var'; +import { _ } from 'meteor/underscore'; +import { moment } from 'meteor/momentjs:moment'; import { OHIF } from 'meteor/ohif:core'; +import { cornerstone } from 'meteor/ohif:cornerstone'; // Use Aldeed's meteor-template-extension package to replace the // default viewportOverlay template. @@ -21,14 +24,21 @@ Template[defaultTemplate].onCreated(() => { if (!instanceMetadata || !tagObject) return; return instanceMetadata.getRawValue(tagObject.tag); }; +}); - // Run this computation every time the image is changed - Tracker.autorun(() => { +Template[defaultTemplate].onRendered(() => { + const instance = Template.instance(); + const { studyInstanceUid, seriesInstanceUid } = instance.data; + + Tracker.autorun(computation => { Session.get('CornerstoneNewImage' + instance.data.viewportIndex); - const { studyInstanceUid, seriesInstanceUid, currentImageIdIndex } = instance.data; + if (computation.firstRun) return; + computation.stop(); + const imageIndex = instance.getImageIndex(); OHIF.studies.loadStudy(studyInstanceUid).then(studyMetadata => { const seriesMetadata = studyMetadata.getSeriesByUID(seriesInstanceUid); - const instanceMetadata = seriesMetadata.getInstanceByIndex(currentImageIdIndex); + const instanceMetadata = seriesMetadata.getInstanceByIndex(imageIndex); + if (!instanceMetadata) return; instance.instanceMetadata.set(instanceMetadata); }); }); @@ -47,10 +57,104 @@ Template[defaultTemplate].helpers({ const instance = Template.instance(); const values = []; values.push(instance.getValueByTagKeyword('PatientSex')); - values.push(instance.getValueByTagKeyword('PatientAge')); + + const patientAge = instance.getValueByTagKeyword('PatientAge'); + const patientBirthDate = instance.getValueByTagKeyword('PatientBirthDate'); + if (patientAge) { + values.push(patientAge); + } else if (patientBirthDate) { + const date = moment(patientBirthDate, 'YYYYMMDD'); + const yearDiff = moment().diff(date, 'years'); + if (yearDiff) { + values.push(yearDiff + 'Y').padStart(4, '0'); + } else { + const monthDiff = moment().diff(date, 'months'); + if (monthDiff) { + values.push(monthDiff + 'M').padStart(4, '0'); + } else { + const dayDiff = moment().diff(date, 'days') || 0; + values.push(dayDiff + 'D').padStart(4, '0'); + } + } + } + return values.filter(value => !!value).join(', '); }, + thickness() { + const instance = Template.instance(); + Session.get('CornerstoneNewImage' + instance.data.viewportIndex); + + return instance.getValueByTagKeyword('SliceThickness'); + }, + + location() { + const instance = Template.instance(); + Session.get('CornerstoneNewImage' + instance.data.viewportIndex); + + const sliceLocation = instance.getValueByTagKeyword('SliceLocation'); + const tablePosition = instance.getValueByTagKeyword('TablePosition'); + const imagePositionPatient = instance.getValueByTagKeyword('ImagePositionPatient'); + return sliceLocation || tablePosition || imagePositionPatient; + }, + + spacingBetweenSlices() { + const instance = Template.instance(); + Session.get('CornerstoneNewImage' + instance.data.viewportIndex); + + // TODO: Otherwise, displays a value derived from successive values + // of Image Position (Patient) (0020,0032) perpendicular to + // the Image Orientation (Patient) (0020,0037) + + return instance.getValueByTagKeyword('SpacingBetweenSlices'); + }, + + zoom() { + const instance = Template.instance(); + const { viewportIndex } = instance.data; + const { getElementIfNotEmpty } = OHIF.viewerbase; + Session.get('CornerstoneImageRendered' + viewportIndex); + + const element = getElementIfNotEmpty(viewportIndex); + if (!element) return; + + const viewport = cornerstone.getViewport(element); + if (!viewport) return; + + return viewport.scale; + }, + + wwwc() { + const instance = Template.instance(); + const { viewportIndex } = instance.data; + const { getElementIfNotEmpty, wlPresets } = OHIF.viewerbase; + Session.get('CornerstoneImageRendered' + viewportIndex); + wlPresets.changeObserver.depend(); + + const element = getElementIfNotEmpty(viewportIndex); + if (!element) return; + + const viewport = cornerstone.getViewport(element); + if (!viewport) return; + + const ww = viewport.voi.windowWidth.toFixed(0); + const wc = viewport.voi.windowCenter.toFixed(0); + const result = [`W: ${ww}, L: ${wc}`]; + + // Check if there's a preset with this W/L + const preset = _.findWhere(OHIF.viewer.wlPresets, { + ww: parseInt(ww), + wc: parseInt(wc) + }); + + // Append the preset name to the result if found + if (preset) { + result .push(`(${preset.id})`); + } + + return result.join(' '); + }, + timepointName() { const instance = Template.instance(); const studyInstanceUid = instance.data.studyInstanceUid; diff --git a/Packages/ohif-viewerbase/client/components/viewer/imageViewerViewport/imageViewerViewport.js b/Packages/ohif-viewerbase/client/components/viewer/imageViewerViewport/imageViewerViewport.js index 64d004e54..eaaef658c 100644 --- a/Packages/ohif-viewerbase/client/components/viewer/imageViewerViewport/imageViewerViewport.js +++ b/Packages/ohif-viewerbase/client/components/viewer/imageViewerViewport/imageViewerViewport.js @@ -5,6 +5,7 @@ import { Session } from 'meteor/session'; import { $ } from 'meteor/jquery'; // OHIF Modules import { OHIF } from 'meteor/ohif:core'; +import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone'; // Local Modules import { StackManager } from '../../../lib/StackManager'; import { setActiveViewport } from '../../../lib/setActiveViewport'; @@ -348,8 +349,7 @@ const loadDisplaySetIntoViewport = (data, templateData) => { }; // Attach the onNewImage callback to the CornerstoneNewImage event - $element.off('CornerstoneNewImage', onNewImage); - $element.on('CornerstoneNewImage', onNewImage); + $element.one('CornerstoneNewImage', onNewImage); // Set a random value for the Session variable in order to trigger an overlay update Session.set('CornerstoneNewImage' + viewportIndex, Math.random()); diff --git a/Packages/ohif-viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.js b/Packages/ohif-viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.js index 9cfd09ece..d41fa7144 100644 --- a/Packages/ohif-viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.js +++ b/Packages/ohif-viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.js @@ -7,6 +7,17 @@ import { viewportOverlayUtils } from '../../../lib/viewportOverlayUtils'; import { getElementIfNotEmpty } from '../../../lib/getElementIfNotEmpty'; import { getStackDataIfNotEmpty } from '../../../lib/getStackDataIfNotEmpty'; +Template.viewportOverlay.onCreated(() => { + const instance = Template.instance(); + + instance.getImageIndex = () => { + const stack = getStackDataIfNotEmpty(instance.data.viewportIndex); + if (!stack || stack.currentImageIdIndex === undefined) return; + + return stack.currentImageIdIndex; + }; +}); + Template.viewportOverlay.helpers({ wwwc() { Session.get('CornerstoneImageRendered' + this.viewportIndex); @@ -217,12 +228,8 @@ Template.viewportOverlay.helpers({ imageIndex() { Session.get('CornerstoneNewImage' + this.viewportIndex); - const stack = getStackDataIfNotEmpty(this.viewportIndex); - if (!stack || stack.currentImageIdIndex === undefined) { - return; - } - - return stack.currentImageIdIndex + 1; + const imageIndex = Template.instance().getImageIndex(); + return _.isUndefined(imageIndex) ? 0 : imageIndex + 1; }, numImages() { diff --git a/Packages/ohif-viewerbase/client/lib/WLPresets.js b/Packages/ohif-viewerbase/client/lib/WLPresets.js index 05702655f..d42a8f47d 100644 --- a/Packages/ohif-viewerbase/client/lib/WLPresets.js +++ b/Packages/ohif-viewerbase/client/lib/WLPresets.js @@ -3,6 +3,7 @@ import { Session } from 'meteor/session'; import { Tracker } from 'meteor/tracker'; import { _ } from 'meteor/underscore'; import { OHIF } from 'meteor/ohif:core'; +import { cornerstone } from 'meteor/ohif:cornerstone'; import { viewportUtils } from './viewportUtils'; const WL_PRESET_CUSTOM = 'Custom'; @@ -70,6 +71,7 @@ class WindowLevelPresetsManager { } else { const WLPresets = OHIF.viewer.wlPresets; for (let index in WLPresets) { + if (!WLPresets.hasOwnProperty(index)) continue; const currentPreset = WLPresets[index]; if (windowCenter === currentPreset.wc && windowWidth === currentPreset.ww) { preset = currentPreset;