Final adjustments on overlay
This commit is contained in:
parent
45c5766501
commit
78c282558c
@ -18,25 +18,22 @@
|
|||||||
<div>{{seriesDescription}}</div>
|
<div>{{seriesDescription}}</div>
|
||||||
<div>{{studyInfo 'AccessionNumber'}}</div>
|
<div>{{studyInfo 'AccessionNumber'}}</div>
|
||||||
<div>{{formatDA (studyInfo 'AcquisitionDate')}} {{formatTM (studyInfo 'AcquisitionTime')}}</div>
|
<div>{{formatDA (studyInfo 'AcquisitionDate')}} {{formatTM (studyInfo 'AcquisitionTime')}}</div>
|
||||||
<div>{{#if seriesNumber}}S: {{seriesNumber}}{{#if gt numImages 1}},{{/if}}{{/if}} {{#if gt numImages 1}}I: {{instanceNumber}} ({{imageIndex}}/{{numImages}}){{/if}}</div>
|
<div>{{#if seriesNumber}}S: {{seriesNumber}}{{#if gt numImages 1}},{{/if}} {{/if}}{{#if gt instanceNumber 0}}I: {{instanceNumber}} {{/if}}{{#if gt numImages 1}}({{imageIndex}}/{{numImages}}){{/if}}</div>
|
||||||
<div class='timepointName'>{{timepointName}}</div>
|
<div class='timepointName'>{{timepointName}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottomright dicomTag">
|
<div class="bottomright dicomTag">
|
||||||
<div>{{#if zoom}}Zoom: {{formatNumberPrecision zoom 0}}%{{/if}}</div>
|
<div class="stationName">{{studyInfo 'StationName'}}</div>
|
||||||
<div class="compressionIndicator">{{compression}}</div>
|
<div class="manufacturerModel">{{studyInfo 'ManufacturersModelName'}}</div>
|
||||||
<div>{{wwwc}}</div>
|
<div class="institutionName">{{studyInfo 'InstitutionName'}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottomleft dicomTag">
|
<div class="bottomleft dicomTag">
|
||||||
<div>{{#if seriesNumber}}Ser: {{seriesNumber}}{{/if}}</div>
|
|
||||||
<div>{{#if gt numImages 1}}Img: {{instanceNumber}} ({{imageIndex}}/{{numImages}}){{/if}}</div>
|
|
||||||
<div>{{#if frameRate}}{{formatNumberPrecision frameRate 2}} FPS{{/if}}</div>
|
|
||||||
<div>{{imageDimensions}}</div>
|
|
||||||
<div>
|
<div>
|
||||||
<span>{{#if location}}Loc: {{formatNumberPrecision location 2}} mm{{/if}}</span>
|
<span>{{#if location}}Loc: {{formatNumberPrecision location 2}} mm{{/if}}</span>
|
||||||
<span>{{#if thickness}}Thick: {{formatNumberPrecision thickness 2}} mm{{/if}}</span>
|
<span>{{#if thickness}}Thick: {{formatNumberPrecision thickness 2}} mm{{/if}}</span>
|
||||||
<span>{{#if spacingBetweenSlices}}Spacing: {{formatNumberPrecision spacingBetweenSlices 2}} mm{{/if}}</span>
|
<span>{{#if spacingBetweenSlices}}Spacing: {{formatNumberPrecision spacingBetweenSlices 2}} mm{{/if}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>{{seriesDescription}}</div>
|
<div>{{#if zoom}}Zoom: {{formatNumberPrecision zoom 2}}x{{/if}}</div>
|
||||||
|
<div>{{wwwc}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,10 @@ import { Template } from 'meteor/templating';
|
|||||||
import { Session } from 'meteor/session';
|
import { Session } from 'meteor/session';
|
||||||
import { Tracker } from 'meteor/tracker';
|
import { Tracker } from 'meteor/tracker';
|
||||||
import { ReactiveVar } from 'meteor/reactive-var';
|
import { ReactiveVar } from 'meteor/reactive-var';
|
||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
import { moment } from 'meteor/momentjs:moment';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { cornerstone } from 'meteor/ohif:cornerstone';
|
||||||
|
|
||||||
// Use Aldeed's meteor-template-extension package to replace the
|
// Use Aldeed's meteor-template-extension package to replace the
|
||||||
// default viewportOverlay template.
|
// default viewportOverlay template.
|
||||||
@ -21,14 +24,21 @@ Template[defaultTemplate].onCreated(() => {
|
|||||||
if (!instanceMetadata || !tagObject) return;
|
if (!instanceMetadata || !tagObject) return;
|
||||||
return instanceMetadata.getRawValue(tagObject.tag);
|
return instanceMetadata.getRawValue(tagObject.tag);
|
||||||
};
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// Run this computation every time the image is changed
|
Template[defaultTemplate].onRendered(() => {
|
||||||
Tracker.autorun(() => {
|
const instance = Template.instance();
|
||||||
|
const { studyInstanceUid, seriesInstanceUid } = instance.data;
|
||||||
|
|
||||||
|
Tracker.autorun(computation => {
|
||||||
Session.get('CornerstoneNewImage' + instance.data.viewportIndex);
|
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 => {
|
OHIF.studies.loadStudy(studyInstanceUid).then(studyMetadata => {
|
||||||
const seriesMetadata = studyMetadata.getSeriesByUID(seriesInstanceUid);
|
const seriesMetadata = studyMetadata.getSeriesByUID(seriesInstanceUid);
|
||||||
const instanceMetadata = seriesMetadata.getInstanceByIndex(currentImageIdIndex);
|
const instanceMetadata = seriesMetadata.getInstanceByIndex(imageIndex);
|
||||||
|
if (!instanceMetadata) return;
|
||||||
instance.instanceMetadata.set(instanceMetadata);
|
instance.instanceMetadata.set(instanceMetadata);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -47,10 +57,104 @@ Template[defaultTemplate].helpers({
|
|||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
const values = [];
|
const values = [];
|
||||||
values.push(instance.getValueByTagKeyword('PatientSex'));
|
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(', ');
|
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() {
|
timepointName() {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
const studyInstanceUid = instance.data.studyInstanceUid;
|
const studyInstanceUid = instance.data.studyInstanceUid;
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { Session } from 'meteor/session';
|
|||||||
import { $ } from 'meteor/jquery';
|
import { $ } from 'meteor/jquery';
|
||||||
// OHIF Modules
|
// OHIF Modules
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone';
|
||||||
// Local Modules
|
// Local Modules
|
||||||
import { StackManager } from '../../../lib/StackManager';
|
import { StackManager } from '../../../lib/StackManager';
|
||||||
import { setActiveViewport } from '../../../lib/setActiveViewport';
|
import { setActiveViewport } from '../../../lib/setActiveViewport';
|
||||||
@ -348,8 +349,7 @@ const loadDisplaySetIntoViewport = (data, templateData) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Attach the onNewImage callback to the CornerstoneNewImage event
|
// Attach the onNewImage callback to the CornerstoneNewImage event
|
||||||
$element.off('CornerstoneNewImage', onNewImage);
|
$element.one('CornerstoneNewImage', onNewImage);
|
||||||
$element.on('CornerstoneNewImage', onNewImage);
|
|
||||||
|
|
||||||
// Set a random value for the Session variable in order to trigger an overlay update
|
// Set a random value for the Session variable in order to trigger an overlay update
|
||||||
Session.set('CornerstoneNewImage' + viewportIndex, Math.random());
|
Session.set('CornerstoneNewImage' + viewportIndex, Math.random());
|
||||||
|
|||||||
@ -7,6 +7,17 @@ import { viewportOverlayUtils } from '../../../lib/viewportOverlayUtils';
|
|||||||
import { getElementIfNotEmpty } from '../../../lib/getElementIfNotEmpty';
|
import { getElementIfNotEmpty } from '../../../lib/getElementIfNotEmpty';
|
||||||
import { getStackDataIfNotEmpty } from '../../../lib/getStackDataIfNotEmpty';
|
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({
|
Template.viewportOverlay.helpers({
|
||||||
wwwc() {
|
wwwc() {
|
||||||
Session.get('CornerstoneImageRendered' + this.viewportIndex);
|
Session.get('CornerstoneImageRendered' + this.viewportIndex);
|
||||||
@ -217,12 +228,8 @@ Template.viewportOverlay.helpers({
|
|||||||
imageIndex() {
|
imageIndex() {
|
||||||
Session.get('CornerstoneNewImage' + this.viewportIndex);
|
Session.get('CornerstoneNewImage' + this.viewportIndex);
|
||||||
|
|
||||||
const stack = getStackDataIfNotEmpty(this.viewportIndex);
|
const imageIndex = Template.instance().getImageIndex();
|
||||||
if (!stack || stack.currentImageIdIndex === undefined) {
|
return _.isUndefined(imageIndex) ? 0 : imageIndex + 1;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return stack.currentImageIdIndex + 1;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
numImages() {
|
numImages() {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { Session } from 'meteor/session';
|
|||||||
import { Tracker } from 'meteor/tracker';
|
import { Tracker } from 'meteor/tracker';
|
||||||
import { _ } from 'meteor/underscore';
|
import { _ } from 'meteor/underscore';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { cornerstone } from 'meteor/ohif:cornerstone';
|
||||||
import { viewportUtils } from './viewportUtils';
|
import { viewportUtils } from './viewportUtils';
|
||||||
|
|
||||||
const WL_PRESET_CUSTOM = 'Custom';
|
const WL_PRESET_CUSTOM = 'Custom';
|
||||||
@ -70,6 +71,7 @@ class WindowLevelPresetsManager {
|
|||||||
} else {
|
} else {
|
||||||
const WLPresets = OHIF.viewer.wlPresets;
|
const WLPresets = OHIF.viewer.wlPresets;
|
||||||
for (let index in WLPresets) {
|
for (let index in WLPresets) {
|
||||||
|
if (!WLPresets.hasOwnProperty(index)) continue;
|
||||||
const currentPreset = WLPresets[index];
|
const currentPreset = WLPresets[index];
|
||||||
if (windowCenter === currentPreset.wc && windowWidth === currentPreset.ww) {
|
if (windowCenter === currentPreset.wc && windowWidth === currentPreset.ww) {
|
||||||
preset = currentPreset;
|
preset = currentPreset;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user