186 lines
6.6 KiB
JavaScript
186 lines
6.6 KiB
JavaScript
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.
|
|
// See https://github.com/aldeed/meteor-template-extension
|
|
const defaultTemplate = 'viewportOverlay';
|
|
Template.longitudinalViewportOverlay.replaces(defaultTemplate);
|
|
|
|
Template[defaultTemplate].onCreated(() => {
|
|
const instance = Template.instance();
|
|
instance.instanceMetadata = new ReactiveVar();
|
|
|
|
const { DICOMTagDescriptions } = OHIF.viewerbase;
|
|
instance.getValueByTagKeyword = tagKeyword => {
|
|
const instanceMetadata = instance.instanceMetadata.get();
|
|
const tagObject = DICOMTagDescriptions.find(tagKeyword);
|
|
if (!instanceMetadata || !tagObject) return;
|
|
return instanceMetadata.getRawValue(tagObject.tag);
|
|
};
|
|
});
|
|
|
|
Template[defaultTemplate].onRendered(() => {
|
|
const instance = Template.instance();
|
|
const { studyInstanceUid, seriesInstanceUid } = instance.data;
|
|
|
|
instance.autorun(computation => {
|
|
Session.get('CornerstoneNewImage' + instance.data.viewportIndex);
|
|
if (computation.firstRun) return;
|
|
computation.stop();
|
|
const imageIndex = instance.getImageIndex();
|
|
|
|
if (!studyInstanceUid || !seriesInstanceUid) {
|
|
return;
|
|
}
|
|
|
|
OHIF.studies.loadStudy(studyInstanceUid).then(study => {
|
|
const studyMetadata = OHIF.viewerbase.getStudyMetadata(study);
|
|
const seriesMetadata = studyMetadata.getSeriesByUID(seriesInstanceUid);
|
|
const instanceMetadata = seriesMetadata.getInstanceByIndex(imageIndex);
|
|
if (!instanceMetadata) return;
|
|
instance.instanceMetadata.set(instanceMetadata);
|
|
});
|
|
});
|
|
});
|
|
|
|
// Add the TimepointName helper to the default template. The
|
|
// HTML of this template is replaced with that of longitudinalViewportOverlay
|
|
Template[defaultTemplate].helpers({
|
|
studyInfo(tagKeyword) {
|
|
const instance = Template.instance();
|
|
instance.instanceMetadata.dep.depend();
|
|
return instance.getValueByTagKeyword(tagKeyword);
|
|
},
|
|
|
|
getGenderAndAge() {
|
|
const instance = Template.instance();
|
|
const values = [];
|
|
values.push(instance.getValueByTagKeyword('PatientSex'));
|
|
|
|
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;
|
|
|
|
const timepointApi = OHIF.viewer.timepointApi;
|
|
if (!timepointApi) return;
|
|
|
|
const timepoints = timepointApi.study(studyInstanceUid);
|
|
if (!timepoints || !timepoints.length) {
|
|
return;
|
|
}
|
|
|
|
const timepoint = timepoints[0];
|
|
|
|
return timepointApi.name(timepoint);
|
|
},
|
|
|
|
linked() {
|
|
const linkedViewports = Session.get('StackImagePositionOffsetSynchronizerLinkedViewports') || [];
|
|
return (linkedViewports.indexOf(this.viewportIndex) !== -1);
|
|
}
|
|
});
|