////////////////////////////////////////////////////////////////////////// // // // This is a generated file. You can view the original // // source in your browser if your browser supports source maps. // // Source maps are supported by all recent versions of Chrome, Safari, // // and Firefox, and by Internet Explorer 11. // // // ////////////////////////////////////////////////////////////////////////// (function () { /* Imports */ var Meteor = Package.meteor.Meteor; var global = Package.meteor.global; var meteorEnv = Package.meteor.meteorEnv; var HTTP = Package.http.HTTP; var $ = Package.jquery.$; var jQuery = Package.jquery.jQuery; var moment = Package['momentjs:moment'].moment; var validate = Package.validatejs.validate; var PersistentSession = Package['cultofcoders:persistent-session'].PersistentSession; var cornerstone = Package['ohif:cornerstone'].cornerstone; var cornerstoneMath = Package['ohif:cornerstone'].cornerstoneMath; var cornerstoneTools = Package['ohif:cornerstone'].cornerstoneTools; var cornerstoneWADOImageLoader = Package['ohif:cornerstone'].cornerstoneWADOImageLoader; var dicomParser = Package['ohif:cornerstone'].dicomParser; var dcmjs = Package['ohif:cornerstone'].dcmjs; var meteorInstall = Package.modules.meteorInstall; var meteorBabelHelpers = Package['babel-runtime'].meteorBabelHelpers; var Promise = Package.promise.Promise; var Symbol = Package['ecmascript-runtime-client'].Symbol; var Map = Package['ecmascript-runtime-client'].Map; var Set = Package['ecmascript-runtime-client'].Set; var WebApp = Package.webapp.WebApp; var Log = Package.logging.Log; var Tracker = Package.deps.Tracker; var Deps = Package.deps.Deps; var Session = Package.session.Session; var DDP = Package['ddp-client'].DDP; var Mongo = Package.mongo.Mongo; var Blaze = Package.ui.Blaze; var UI = Package.ui.UI; var Handlebars = Package.ui.Handlebars; var Spacebars = Package.spacebars.Spacebars; var Template = Package['templating-runtime'].Template; var check = Package.check.check; var Match = Package.check.Match; var _ = Package.underscore._; var Random = Package.random.Random; var EJSON = Package.ejson.EJSON; var LaunchScreen = Package['launch-screen'].LaunchScreen; var HTML = Package.htmljs.HTML; /* Package-scope variables */ var ProtocolEngine, dialogPolyfill; var require = meteorInstall({"node_modules":{"meteor":{"ohif:viewerbase":{"client":{"components":{"basic":{"layout":{"template.layout.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/basic/layout/template.layout.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("layout"); Template["layout"] = new Template("Template.layout", (function() { var view = this; return Spacebars.include(view.lookupTemplate("yield")); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"loadingText":{"template.loadingText.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/basic/loadingText/template.loadingText.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("loadingText"); Template["loadingText"] = new Template("Template.loadingText", (function() { var view = this; return HTML.Raw('
\n Loading... \n
'); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"errorText":{"template.errorText.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/basic/errorText/template.errorText.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("errorText"); Template["errorText"] = new Template("Template.errorText", (function() { var view = this; return HTML.DIV({ class: "errorTextDiv" }, "\n Error: ", Blaze.View("lookup:error", function() { return Spacebars.mustache(view.lookup("error")); }), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"removableBackdrop":{"template.removableBackdrop.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/basic/removableBackdrop/template.removableBackdrop.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("removableBackdrop"); Template["removableBackdrop"] = new Template("Template.removableBackdrop", (function() { var view = this; return HTML.Raw('
\n
'); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"aboutModal":{"template.aboutModal.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/basic/aboutModal/template.aboutModal.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("aboutModal"); Template["aboutModal"] = new Template("Template.aboutModal", (function() { var view = this; return Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("extend"), view.lookup("."), Spacebars.kw({ id: "aboutModal", dialogClass: "modal-lg", title: "About" })); }, function() { return Spacebars.include(view.lookupTemplate("dialogSimple"), function() { return [ "\n ", HTML.A({ target: "_blank", class: "forkOnGithub", href: function() { return Spacebars.mustache(view.lookup("githubUrl")); } }, "\n ", HTML.IMG({ src: "https://camo.githubusercontent.com/365986a132ccd6a44c23a9169022c0b5c890c387/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67", alt: "Fork me on GitHub", "data-canonical-src": "https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" }), "\n "), "\n ", HTML.DIV({ class: "logo p-x-3 p-y-3 clearfix" }, "\n ", HTML.SVG({ class: "logoImage pull-left" }, "\n ", HTML.USE({ "xlink:href": function() { return Spacebars.mustache(view.lookup("absoluteUrl"), "packages/ohif_viewerbase/assets/icons.svg#icon-ohif-logo"); } }), "\n "), "\n ", HTML.A({ class: "logoText pull-left", target: "_blank", href: "http://ohif.org" }, "\n Open Health Imaging Foundation DICOM Viewer\n "), "\n "), "\n ", HTML.DIV({ class: "p-x-1 p-y-1 m-y-2" }, "\n ", HTML.A({ class: "btn btn-default inline", target: "_blank", href: "https://groups.google.com/forum/#!forum/cornerstone-platform" }, "\n Visit the forum\n "), "\n ", HTML.A({ class: "btn btn-default inline", target: "_blank", href: "https://github.com/OHIF/Viewers/issues" }, "\n Report an issue\n "), "\n "), "\n ", HTML.DIV({ class: "p-y-1 p-x-1" }, "\n ", HTML.H3("Version Information"), "\n ", HTML.TABLE({ class: "table table-responsive" }, "\n ", HTML.THEAD("\n ", HTML.TR("\n ", HTML.TH("Name"), "\n ", HTML.TH("Value"), "\n "), "\n "), "\n ", HTML.TBODY("\n ", HTML.TR("\n ", HTML.TD("Repository URL"), "\n ", HTML.TD("\n ", HTML.A({ target: "_blank", href: function() { return Spacebars.mustache(view.lookup("githubUrl")); } }, Blaze.View("lookup:githubUrl", function() { return Spacebars.mustache(view.lookup("githubUrl")); })), "\n "), "\n "), "\n ", HTML.TR("\n ", HTML.TD("Last Commit Hash"), "\n ", HTML.TD("\n ", HTML.A({ target: "_blank", href: function() { return [ Spacebars.mustache(view.lookup("githubUrl")), "/commit/", Spacebars.mustache(view.lookup("gitRev"), "long") ]; } }, "\n ", Blaze.View("lookup:gitRev", function() { return Spacebars.mustache(view.lookup("gitRev"), "long"); }), "\n "), "\n "), "\n "), "\n ", HTML.TR("\n ", HTML.TD("Latest Tag"), "\n ", HTML.TD("\n ", HTML.A({ target: "_blank", href: function() { return [ Spacebars.mustache(view.lookup("githubUrl")), "/releases/tag/", Spacebars.mustache(view.lookup("gitRev"), "tag") ]; } }, "\n ", Blaze.View("lookup:gitRev", function() { return Spacebars.mustache(view.lookup("gitRev"), "tag"); }), "\n "), "\n "), "\n "), "\n ", HTML.TR("\n ", HTML.TD("Branch"), "\n ", HTML.TD("\n ", HTML.A({ target: "_blank", href: function() { return [ Spacebars.mustache(view.lookup("githubUrl")), "/tree/", Spacebars.mustache(view.lookup("gitRev"), "branch") ]; } }, "\n ", Blaze.View("lookup:gitRev", function() { return Spacebars.mustache(view.lookup("gitRev"), "branch"); }), "\n "), "\n "), "\n "), "\n "), "\n "), "\n "), "\n " ]; }); }); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"aboutModal.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/basic/aboutModal/aboutModal.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.aboutModal.helpers({ githubUrl: function () { return 'https://github.com/OHIF/Viewers'; } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }}},"studyBrowser":{"studyBrowser":{"template.studyBrowser.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/studyBrowser/studyBrowser/template.studyBrowser.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("studyBrowser"); Template["studyBrowser"] = new Template("Template.studyBrowser", (function() { var view = this; return HTML.DIV({ class: "studyBrowser" }, "\n ", HTML.DIV({ class: "scrollableStudyThumbnails" }, "\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(view.lookup("studies")), _variable: "study" }; }, function() { return [ "\n ", Blaze.Each(function() { return { _sequence: Spacebars.dataMustache(view.lookup("sort"), Spacebars.dataMustache(view.lookup("studyThumbnails"), view.lookup("study")), view.lookup("thumbnailSortBy"), view.lookup("thumbnailSortType")), _variable: "thumbnail" }; }, function() { return [ "\n ", Blaze._TemplateWith(function() { return { thumbnail: Spacebars.call(view.lookup("thumbnail")) }; }, function() { return Spacebars.include(view.lookupTemplate("thumbnailEntry")); }), "\n " ]; }), "\n " ]; }), "\n "), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"studyBrowser.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/studyBrowser/studyBrowser/studyBrowser.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 1); Template.studyBrowser.helpers({ studies: function () { // @TypeSafeStudies return OHIF.viewer.Studies.findAllBy({ selected: true }); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"thumbnailEntry":{"template.thumbnailEntry.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/studyBrowser/thumbnailEntry/template.thumbnailEntry.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("thumbnailEntry"); Template["thumbnailEntry"] = new Template("Template.thumbnailEntry", (function() { var view = this; return Blaze.Let({ stack: function() { return Spacebars.call(Spacebars.dot(view.lookup("."), "thumbnail", "stack")); } }, function() { return [ "\n ", HTML.DIV({ class: function() { return [ "thumbnailEntry noselect m-t-1 m-b-2 ", Spacebars.mustache(view.lookup("draggableClass")), " ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("isDisplaySetActive"), Spacebars.dot(view.lookup("stack"), "displaySetInstanceUid"), view.lookup("viewportIndex")); }, function() { return "active"; }) ]; } }, "\n ", HTML.DIV({ class: "p-x-1" }, "\n ", Blaze._TemplateWith(function() { return { thumbnail: Spacebars.call(view.lookup("thumbnail")), currentStudy: Spacebars.call(view.lookup("currentStudy")) }; }, function() { return Spacebars.include(view.lookupTemplate("imageThumbnail")); }), "\n "), "\n ", HTML.DIV({ class: function() { return [ "seriesDetails flex-h m-x-1 ", Blaze.Unless(function() { return Spacebars.call(Spacebars.dot(view.lookup("stack"), "seriesDescription")); }, function() { return "info-only"; }) ]; } }, "\n ", HTML.DIV({ class: "seriesDescription flex-grow" }, "\n ", Blaze.View("lookup:stack.seriesDescription", function() { return Spacebars.mustache(Spacebars.dot(view.lookup("stack"), "seriesDescription")); }), "\n "), "\n ", HTML.DIV({ class: "seriesInformation" }, "\n ", HTML.DIV({ class: "item item-series clearfix" }, "\n ", HTML.DIV({ class: "icon" }, "S:"), "\n ", HTML.DIV({ class: "value" }, Blaze.View("lookup:stack.seriesNumber", function() { return Spacebars.mustache(Spacebars.dot(view.lookup("stack"), "seriesNumber")); })), "\n "), "\n ", Blaze.Unless(function() { return Spacebars.dataMustache(view.lookup("isUndefined"), view.lookup("instanceNumber")); }, function() { return [ "\n ", HTML.DIV({ class: "item item-series clearfix" }, "\n ", HTML.DIV({ class: "icon" }, "I:"), "\n ", HTML.DIV({ class: "value" }, Blaze.View("lookup:instanceNumber", function() { return Spacebars.mustache(view.lookup("instanceNumber")); })), "\n "), "\n " ]; }), "\n ", HTML.DIV({ class: "item item-frames clearfix" }, "\n ", HTML.DIV({ class: "icon" }, HTML.DIV()), "\n ", HTML.DIV({ class: "value" }, Blaze.View("lookup:stack.numImageFrames", function() { return Spacebars.mustache(Spacebars.dot(view.lookup("stack"), "numImageFrames")); })), "\n "), "\n "), "\n "), "\n "), "\n " ]; }); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"thumbnailEntry.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/studyBrowser/thumbnailEntry/thumbnailEntry.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 1); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 2); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 3); var thumbnailDragHandlers; module.watch(require("../../../lib/thumbnailDragHandlers"), { thumbnailDragHandlers: function (v) { thumbnailDragHandlers = v; } }, 4); Template.thumbnailEntry.onCreated(function () { var instance = Template.instance(); // Check if the thumbnails will be draggable or clickable var isIndexUndefined = _.isUndefined(instance.data.viewportIndex); instance.isDragAndDrop = isIndexUndefined && OHIF.uiSettings.leftSidebarDragAndDrop !== false; }); Template.thumbnailEntry.events({ // Event handlers for drag and drop 'mousedown .thumbnailEntry': function (event, instance) { var data = instance.data.thumbnail.stack; if (!instance.isDragAndDrop || event.button !== 0) return; thumbnailDragHandlers.thumbnailDragStartHandler(event, data); }, 'touchstart .thumbnailEntry': function (event, instance) { var data = instance.data.thumbnail.stack; if (!instance.isDragAndDrop) return; thumbnailDragHandlers.thumbnailDragStartHandler(event, data); }, 'touchmove .thumbnailEntry': function (event, instance) { if (!instance.isDragAndDrop) return; thumbnailDragHandlers.thumbnailDragHandler(event); }, 'touchend .thumbnailEntry': function (event, instance) { var data = instance.data.thumbnail.stack; if (!instance.isDragAndDrop) return; thumbnailDragHandlers.thumbnailDragEndHandler(event, data); }, // Event handlers for click (quick switch) 'click .thumbnailEntry': function (event, instance) { if (instance.isDragAndDrop) return; // Get the thumbnail stack data var data = instance.data.thumbnail.stack; // Get the viewport index var viewportIndex = instance.data.viewportIndex; if (_.isUndefined(viewportIndex)) { viewportIndex = Session.get('activeViewport') || 0; } // Rerender the viewport using the clicked thumbnail data OHIF.viewerbase.layoutManager.rerenderViewportWithNewDisplaySet(viewportIndex, data); }, // Event handlers for double click 'dblclick .thumbnailEntry': function (event, instance) { if (!instance.isDragAndDrop) return; // Get the active viewport index and total number of viewports... var viewportCount = OHIF.viewerbase.layoutManager.getNumberOfViewports(); var viewportIndex = Session.get('activeViewport') || 0; if (viewportIndex >= viewportCount) { viewportIndex = viewportCount > 0 ? viewportCount - 1 : 0; } // Get the thumbnail stack data var data = instance.data.thumbnail.stack; // Rerender the viewport using the clicked thumbnail data OHIF.viewerbase.layoutManager.rerenderViewportWithNewDisplaySet(viewportIndex, data); } }); Template.thumbnailEntry.helpers({ draggableClass: function () { return Template.instance().isDragAndDrop ? 'draggable' : ''; }, instanceNumber: function () { var thumbnail = Template.instance().data.thumbnail; if (!thumbnail) { return; } var stack = thumbnail.stack; if (!stack) { return; } // No need to show instance number for single-frame images if (!stack.isMultiFrame) { return; } var firstImage = stack.images[0]; if (!firstImage) { return; } return firstImage.instanceNumber; } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"imageThumbnail":{"template.imageThumbnail.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/studyBrowser/imageThumbnail/template.imageThumbnail.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("imageThumbnail"); Template["imageThumbnail"] = new Template("Template.imageThumbnail", (function() { var view = this; return HTML.DIV({ class: "imageThumbnail" }, HTML.Raw('\n
\n \n
\n '), HTML.DIV({ class: function() { return [ "imageThumbnailLoadingIndicator\n thumbnailLoadingIndicator\n ", Blaze.If(function() { return Spacebars.call(view.lookup("isLoading")); }, function() { return "d-block"; }) ]; } }, "\n ", HTML.P("Loading ", Blaze.View("lookup:percentComplete", function() { return Spacebars.mustache(view.lookup("percentComplete")); })), "\n "), "\n ", HTML.DIV({ class: function() { return [ "imageThumbnailErrorLoadingIndicator\n thumbnailLoadingIndicator\n ", Blaze.If(function() { return Spacebars.call(view.lookup("hasLoadingError")); }, function() { return "d-block"; }) ]; } }, "\n ", HTML.Raw("

Error

"), "\n "), "\n ", Blaze.If(function() { return Spacebars.call(view.lookup("showStackLoadingProgressBar")); }, function() { return [ "\n ", HTML.DIV({ class: "imageThumbnailProgressBar" }, "\n ", HTML.DIV({ class: "imageThumbnailProgressBarInner", style: function() { return [ "width:", Spacebars.mustache(view.lookup("stackPercentComplete")), "%" ]; } }), "\n "), "\n " ]; }), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"imageThumbnail.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/studyBrowser/imageThumbnail/imageThumbnail.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 1); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 2); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 3); var cornerstone; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; } }, 4); /** * Asynchronous wrapper around Cornerstone's renderToCanvas method. * * @param {HTMLElement} canvasElement An HTML element * @param {Image} image A Cornerstone Image * * @return {Promise} A promise tracking the progress of the rendering. Resolves empty. */ function renderAsync(canvasElement, image) { return new Promise(function (resolve, reject) { try { cornerstone.renderToCanvas(canvasElement, image); resolve(); } catch (error) { reject(error); } }); } Template.imageThumbnail.onCreated(function () { var instance = Template.instance(); instance.isLoading = new ReactiveVar(false); instance.hasLoadingError = new ReactiveVar(false); // Get the image ID for current thumbnail instance.getThumbnailImageId = function () { var settingPath = 'public.ui.useMiddleSeriesInstanceAsThumbnail'; var useMiddleFrame = OHIF.utils.ObjectPath.get(Meteor.settings, settingPath); var stack = instance.data.thumbnail.stack; var lastIndex = (stack.numImageFrames || stack.images.length || 1) - 1; var imageIndex = useMiddleFrame ? Math.floor(lastIndex / 2) : 0; var imageInstance; if (stack.isMultiFrame) { imageInstance = stack.images[0]; } else { imageInstance = stack.images[imageIndex]; imageIndex = undefined; } return imageInstance.getImageId(imageIndex, true); }; }); Template.imageThumbnail.onRendered(function () { var instance = Template.instance(); // Declare DOM and jQuery objects var $parent = instance.$('.imageThumbnail'); var $thumbnailElement = $parent.find('.imageThumbnailCanvas'); instance.refreshImage = function () { var imageElement = $thumbnailElement.find('img').get(0); // Activate the loading state instance.isLoading.set(true); instance.hasLoadingError.set(false); // Clear the previous image imageElement.removeAttribute('src'); // Define a handler for success on image load var loadSuccess = function (image) { // This is an off-screen canvas. It's used to get dataURL images by using // cornerstone.renderToCanvas function. var canvasElement = document.createElement('canvas'); canvasElement.width = 193; canvasElement.height = 123; // Render the image to canvas to be able to get its dataURL renderAsync(canvasElement, image).then(function () { instance.isLoading.set(false); imageElement.src = canvasElement.toDataURL('image/jpeg', 1); }); }; // Define a handler for error on image load var loadError = function () { instance.isLoading.set(false); instance.hasLoadingError.set(true); }; // Call cornerstone image loader with the defined handlers cornerstone.loadAndCacheImage(instance.imageId).then(loadSuccess, loadError); }; // Run this computation every time the current study is changed instance.autorun(function () { // Check if there is a reactive var set for current study if (instance.data.currentStudy) { // Register a dependency from this computation on current study instance.data.currentStudy.dep.depend(); } // Depend on external data and re-run this computation when it changes Template.currentData(); // Get the image ID. If it is the same as the currently rendered imageId, // refresh the image. var imageId = instance.getThumbnailImageId(); if (imageId !== instance.imageId) { instance.imageId = imageId; instance.refreshImage(); } }); }); Template.imageThumbnail.helpers({ // Executed every time the thumbnail image loading progress is changed percentComplete: function () { var instance = Template.instance(); // Get the encoded image ID for thumbnail var encodedImageId = OHIF.string.encodeId(instance.imageId); // Register a dependency from this computation on Session key var percentComplete = Session.get('CornerstoneThumbnailLoadProgress' + encodedImageId); // Return the complete percent amount of the image loading if (percentComplete && percentComplete !== 100) { return percentComplete + '%'; } }, // Return how much the stack has already loaded stackPercentComplete: function () { var stack = Template.instance().data.thumbnail.stack; var progress = Session.get("StackProgress:" + stack.displaySetInstanceUid); return progress && progress.percentComplete; }, showStackLoadingProgressBar: function () { return OHIF.uiSettings.showStackLoadingProgressBar; }, isLoading: function () { return Template.instance().isLoading.get(); }, hasLoadingError: function () { return Template.instance().hasLoadingError.get(); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }}},"viewer":{"imageViewerViewport":{"template.imageViewerViewport.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/imageViewerViewport/template.imageViewerViewport.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("imageViewerViewport"); Template["imageViewerViewport"] = new Template("Template.imageViewerViewport", (function() { var view = this; return [ HTML.Raw('
\n
\n
\n Please drag a stack here to view images.\n
\n '), Spacebars.include(view.lookupTemplate("viewportOverlay")), "\n ", Spacebars.include(view.lookupTemplate("loadingIndicator")), "\n ", Spacebars.include(view.lookupTemplate("viewportOrientationMarkers")) ]; })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"imageViewerViewport.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/imageViewerViewport/imageViewerViewport.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 1); var Tracker; module.watch(require("meteor/tracker"), { Tracker: function (v) { Tracker = v; } }, 2); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 3); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 4); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 5); var cornerstone, cornerstoneTools; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; }, cornerstoneTools: function (v) { cornerstoneTools = v; } }, 6); var StackManager; module.watch(require("../../../lib/StackManager"), { StackManager: function (v) { StackManager = v; } }, 7); var setActiveViewport; module.watch(require("../../../lib/setActiveViewport"), { setActiveViewport: function (v) { setActiveViewport = v; } }, 8); var imageViewerViewportData; module.watch(require("../../../lib/imageViewerViewportData"), { imageViewerViewportData: function (v) { imageViewerViewportData = v; } }, 9); var updateCrosshairsSynchronizer; module.watch(require("../../../lib/updateCrosshairsSynchronizer"), { updateCrosshairsSynchronizer: function (v) { updateCrosshairsSynchronizer = v; } }, 10); var toolManager; module.watch(require("../../../lib/toolManager"), { toolManager: function (v) { toolManager = v; } }, 11); var updateOrientationMarkers; module.watch(require("../../../lib/updateOrientationMarkers"), { updateOrientationMarkers: function (v) { updateOrientationMarkers = v; } }, 12); var getInstanceClassDefaultViewport; module.watch(require("../../../lib/instanceClassSpecificViewport"), { getInstanceClassDefaultViewport: function (v) { getInstanceClassDefaultViewport = v; } }, 13); var OHIFError; module.watch(require("../../../lib/classes/OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 14); var allCornerstoneEvents = ['click', 'cornerstonetoolsmousedown', 'cornerstonetoolsmousedownactivate', 'cornerstonetoolsmouseclick', 'cornerstonetoolsmousedrag', 'cornerstonetoolsmouseup', 'cornerstonetoolsmousewheel', 'cornerstonetoolsdoubletap', 'cornerstonetoolstouchpress', 'cornerstonetoolsmultitouchstart', 'cornerstonetoolsmultitouchstartactive', 'cornerstonetoolsmultitouchdrag']; var PLUGIN_CORNERSTONE = 'cornerstone'; /** * This function loads a study series into a viewport element. * * @param data {object} Object containing the study, series, and viewport element to be used */ var loadDisplaySetIntoViewport = function (data, templateData) { var wlPresets = OHIF.viewerbase.wlPresets; OHIF.log.info('imageViewerViewport loadDisplaySetIntoViewport'); // Make sure we have all the data required to render the series if (!data.study || !data.displaySet || !data.element) { OHIF.log.warn('loadDisplaySetIntoViewport: No Study, Display Set, or Element provided'); return; } // Get the current element and it's index in the list of all viewports // The viewport index is often used to store information about a viewport element var element = data.element; var viewportIndex = templateData.viewportIndex; var layoutManager = OHIF.viewerbase.layoutManager; layoutManager.viewportData = layoutManager.viewportData || {}; layoutManager.viewportData[viewportIndex] = layoutManager.viewportData[viewportIndex] || {}; layoutManager.viewportData[viewportIndex].viewportIndex = viewportIndex; // Stop here if no data was defined for the viewer if (!OHIF.viewer.data) return; // This data will be saved so that the viewport can be reloaded to the same state later OHIF.viewer.data.loadedSeriesData[viewportIndex] = {}; // Create shortcut to displaySet var displaySet = data.displaySet; // Get stack from Stack Manager var stack = StackManager.findOrCreateStack(data.study, displaySet); // If is a clip, updates the global FPS for cine dialog if (stack.isClip && stack.frameRate > 0) { // Sets the global variable OHIF.viewer.cine.framesPerSecond = parseFloat(stack.frameRate); // Update the cine dialog FPS Session.set('UpdateCINE', Math.random()); } // Shortcut for array with image IDs var imageIds = stack.imageIds; // Define the current image stack using the newly created image IDs stack = { currentImageIdIndex: data.currentImageIdIndex > 0 && data.currentImageIdIndex < imageIds.length ? data.currentImageIdIndex : 0, imageIds: imageIds, displaySetInstanceUid: data.displaySetInstanceUid }; // Get the current image ID for the stack that will be rendered var imageId = imageIds[stack.currentImageIdIndex]; // Save the current image ID inside the template data so it can be // retrieved from the template helpers templateData.imageId = imageId; // Save the current image ID inside the ViewportLoading object. // // The ViewportLoading object relates the viewport elements with whichever // image is currently being loaded into them. This is useful so that we can // place progress (download %) for each image inside the proper viewports. window.ViewportLoading[viewportIndex] = imageId; // Enable Cornerstone for the viewport element var options = { renderer: OHIF.cornerstone.renderer }; cornerstone.enable(element, options); // Get the handler functions that will run when loading has finished or thrown // an error. These are used to show/hide loading / error text boxes on each viewport. var endLoadingHandler = cornerstoneTools.loadHandlerManager.getEndLoadHandler(); var errorLoadingHandler = cornerstoneTools.loadHandlerManager.getErrorLoadingHandler(); // Get the current viewport settings var viewport = cornerstone.getViewport(element); var studyInstanceUid = data.studyInstanceUid, seriesInstanceUid = data.seriesInstanceUid, displaySetInstanceUid = data.displaySetInstanceUid, currentImageIdIndex = data.currentImageIdIndex; // Store the current series data inside the Layout Manager layoutManager.viewportData[viewportIndex] = { imageId: imageId, studyInstanceUid: studyInstanceUid, seriesInstanceUid: seriesInstanceUid, displaySetInstanceUid: displaySetInstanceUid, currentImageIdIndex: currentImageIdIndex, viewport: viewport || data.viewport, viewportIndex: viewportIndex, plugin: PLUGIN_CORNERSTONE }; // Handle the case where the imageId isn't loaded correctly and the // imagePromise returns undefined // To test, uncomment the next line // data.imageId = 'AfileThatDoesntWork'; // For testing only! var imagePromise; try { imagePromise = cornerstone.loadAndCacheImage(imageId); } catch (error) { OHIF.log.info(error); if (!imagePromise) { errorLoadingHandler(element, imageId, error); return; } } // Additional tasks for metadata provider. If using your own // metadata provider, this may not be necessary. // updateMetadata is important, though, to update image metadata that // for any reason was missing some information such as rows, columns, // sliceThickness, etc (See MetadataProvider class from ohif-cornerstone package) var metadataProvider = OHIF.viewer.metadataProvider; var isUpdateMetadataDefined = metadataProvider && typeof metadataProvider.updateMetadata === 'function'; // loadAndCacheImage configurable callbacks var callbacks = imageViewerViewportData.callbacks; // Check if it has before loadAndCacheImage callback if (typeof callbacks.before === 'function') { OHIF.log.info('imageViewerViewport before loadAndCacheImage callback'); callbacks.before(imagePromise, templateData); } // Start loading the image. imagePromise.then(function (image) { var enabledElement; try { enabledElement = cornerstone.getEnabledElement(element); } catch (error) { OHIF.log.warn('Viewport destroyed before loaded image could be displayed'); return; } // Caches element's jQuery object var $element = $(element); // Update the enabled element with the image and viewport data // This is not usually necessary, but we need them stored in case // a sopClassUid-specific viewport setting is present. enabledElement.image = image; enabledElement.viewport = cornerstone.getDefaultViewport(enabledElement.canvas, image); if (isUpdateMetadataDefined) { // Update the metaData for missing fields metadataProvider.updateMetadata(image); } // Check if there are default viewport settings for this sopClassUid if (!displaySet.images || !displaySet.images.length) { return; } var instance = displaySet.images[0]; var instanceClassViewport = getInstanceClassDefaultViewport(instance, enabledElement, image.imageId); // If there are sopClassUid-specific viewport settings, apply them if (instanceClassViewport) { cornerstone.displayImage(element, image, instanceClassViewport); // Mark that this element should not be fit to the window in the resize listeners // TODO: Find another way to do this? enabledElement.fitToWindow = false; // Resize the canvas to fit the current viewport element size. cornerstone.resize(element, false); } else if (data.viewport) { // If there is a saved object containing Cornerstone viewport data // (e.g. scale, invert, window settings) in the input data, apply it now. cornerstone.displayImage(element, image, data.viewport); // Resize the canvas to fit the current viewport element size. Fit the displayed // image to the canvas dimensions. cornerstone.resize(element, true); } else { // If no saved viewport settings or modality-specific settings exists, // display the loaded image in the viewport element with no loaded viewport // settings. cornerstone.displayImage(element, image); // Resize the canvas to fit the current viewport element size. Fit the displayed // image to the canvas dimensions. cornerstone.resize(element, true); } // Set/store W/L preset data to Default on first display wlPresets.updateElementWLPresetData(element); // Remove the data for this viewport from the ViewportLoading object // This will stop the loading percentage complete from being displayed. delete window.ViewportLoading[viewportIndex]; // Call the handler function that represents the end of the image loading phase // (e.g. hide the progress text box) endLoadingHandler(element, image); // Remove the 'empty' class from the viewport to hide any instruction text element.classList.remove('empty'); // Hide the viewport instructions (i.e. 'Drag a stack here') and show // the viewport overlay data. $element.siblings('.viewportInstructions').hide(); $element.siblings('.imageViewerViewportOverlay').show(); // Add stack state managers for the stack tool, CINE tool, and reference lines cornerstoneTools.addStackStateManager(element, ['stack', 'playClip', 'referenceLines']); // Enable orientation markers, if applicable updateOrientationMarkers(element); // Clear any old stack data cornerstoneTools.clearToolState(element, 'stack'); cornerstoneTools.addToolState(element, 'stack', stack); // Set the default CINE settings var multiframeMetadata = instance.getDataProperty('multiframeMetadata'); var fps; if (multiframeMetadata && multiframeMetadata.averageFrameRate > 0) { fps = multiframeMetadata.averageFrameRate; } else { fps = OHIF.viewer.cine.framesPerSecond; } var cineToolData = { loop: OHIF.viewer.cine.loop, framesPerSecond: fps }; cornerstoneTools.addToolState(element, 'playClip', cineToolData); // Autoplay datasets that have framerates set if (multiframeMetadata && multiframeMetadata.isMultiframeImage && multiframeMetadata.averageFrameRate > 0) { cornerstoneTools.playClip(element); } // Enable mouse, mouseWheel, touch, and keyboard input on the element cornerstoneTools.mouseInput.enable(element); cornerstoneTools.touchInput.enable(element); cornerstoneTools.mouseWheelInput.enable(element); cornerstoneTools.keyboardInput.enable(element); // Use the tool manager to enable the currently active tool for this // newly rendered element var activeTool = toolManager.getActiveTool(); toolManager.setActiveTool(activeTool, [element]); // Define a function to run whenever the Cornerstone viewport is rendered // (e.g. following a change of window or zoom) var onImageRendered = function (event) { var eventData = event.detail; var viewport = eventData.viewport, element = eventData.element; // Attention: Adding OHIF.log.info in this function may decrease the performance // since this callback function is called multiple times (eg: when a tool is // enabled/disabled -> cornerstone[toolName].tool.enable) if (!layoutManager.viewportData[viewportIndex]) { OHIF.log.warn("onImageRendered: LayoutManager has no viewport data for this viewport index?: " + viewportIndex); } // Use Session to trigger reactive updates in the viewportOverlay helper functions // This lets the viewport overlay always display correct window / zoom values Session.set('CornerstoneImageRendered' + viewportIndex, Math.random()); // Save the current viewport into the OHIF.viewer.data global variable layoutManager.viewportData[viewportIndex].viewport = viewport; OHIF.viewer.data.loadedSeriesData[viewportIndex].viewport = viewport; // Update the W/L Preset data, if necessary wlPresets.updateElementWLPresetData(element); // Check if it has onImageRendered loadAndCacheImage callback if (typeof callbacks.onImageRendered === 'function') { callbacks.onImageRendered(event, eventData, viewportIndex, templateData); } }; // Attach the onImageRendered callback to the CornerstoneImageRendered event element.removeEventListener('cornerstoneimagerendered', onImageRendered); element.addEventListener('cornerstoneimagerendered', onImageRendered); // Set a random value for the Session variable in order to trigger an overlay update Session.set('CornerstoneImageRendered' + viewportIndex, Math.random()); // Define a function to run whenever the Cornerstone viewport changes images // (e.g. during scrolling) var onNewImage = function (event) { var eventData = event.detail; // Attention: Adding OHIF.log.info in this function may decrease the performance // since this callback function is called multiple times (eg: when a tool is // enabled/disabled -> cornerstone[toolName].tool.enable) if (isUpdateMetadataDefined) { // Update the metaData for missing fields metadataProvider.updateMetadata(eventData.enabledElement.image); } // Update the templateData with the new imageId // This allows the template helpers to update reactively templateData.imageId = eventData.enabledElement.image.imageId; Session.set('CornerstoneNewImage' + viewportIndex, Math.random()); layoutManager.viewportData[viewportIndex].imageId = eventData.enabledElement.image.imageId; // Get the element and stack data var element = event.target; var toolData = cornerstoneTools.getToolState(element, 'stack'); if (!toolData || !toolData.data || !toolData.data.length) { return; } // Update orientation markers in case new slices don't have the same orientation // as the first slice updateOrientationMarkers(element); // If this viewport is displaying a stack of images, save the current image // index in the stack to the global OHIF.viewer.data object. var stack = cornerstoneTools.getToolState(element, 'stack'); if (stack && stack.data.length && stack.data[0].imageIds.length > 1) { var imageIdIndex = stack.data[0].imageIds.indexOf(templateData.imageId); layoutManager.viewportData[viewportIndex].currentImageIdIndex = imageIdIndex; OHIF.viewer.data.loadedSeriesData[viewportIndex].currentImageIdIndex = imageIdIndex; } var wlPresetData = cornerstone.getElementData(element, 'wlPreset'); var wlPresetDataName = wlPresetData && wlPresetData.name; wlPresets.applyWLPreset(wlPresetDataName, element); // Check if it has onNewImage loadAndCacheImage callback if (typeof callbacks.onNewImage === 'function') { callbacks.onNewImage(event, eventData, viewportIndex, templateData); } }; // Attach the onNewImage callback to the CornerstoneNewImage event element.removeEventListener('cornerstonenewimage', onNewImage); element.addEventListener('cornerstonenewimage', onNewImage); // Set a random value for the Session variable in order to trigger an overlay update Session.set('CornerstoneNewImage' + viewportIndex, Math.random()); var onStackScroll = function () { // Attention: Adding OHIF.log.info in this function may decrease the performance // since this callback function is called multiple times (eg: when a tool is // enabled/disabled -> cornerstone[toolName].tool.enable) // Update the imageSlider value Session.set('CornerstoneNewImage' + viewportIndex, Math.random()); }; element.removeEventListener('cornerstonestackscroll', onStackScroll); if (stack.imageIds.length > 1) { element.addEventListener('cornerstonestackscroll', onStackScroll); } // Define a function to trigger an event whenever a new viewport is being used // This is used to update the value of the "active viewport", when the user interacts // with a new viewport element var sendActivationTrigger = function (event) { var eventData = event && event.detail; // Attention: Adding OHIF.log.info in this function decrease the performance // since this callback function is called multiple times (eg: when a tool is // enabled/disabled -> cornerstone[toolName].tool.enable) // Reset the focus, even if we don't need to re-enable reference lines or prefetching var element = eventData && eventData.element || event && event.currentTarget; if (!element) return; var $element = $(element); // Stop here if we don't have eventData set if (!eventData) return; // Check if the current active viewport in the Meteor Session // Is the same as the viewport in which the activation event was fired. // If it was, no changes are necessary, so stop here. var activeViewportIndex = Session.get('activeViewport'); if (viewportIndex === activeViewportIndex) return; $element.focus(); OHIF.log.info('imageViewerViewport sendActivationTrigger'); // Otherwise, trigger an 'OHIFActivateViewport' event to be handled by the Template event // handler eventData.viewportIndex = viewportIndex; var customEvent = $.Event('OHIFActivateViewport', eventData); // Need to overwrite the type set in the original event customEvent.type = 'OHIFActivateViewport'; $element.trigger(customEvent, eventData); }; // Handle mouseenter event to send viewport activation trigger only if there is no focused dropdown var onMouseEnter = function () { if ($(':focus').closest('.dropdown').length) return; sendActivationTrigger(); }; // Attach the sendActivationTrigger function to all of the Cornerstone interaction events allCornerstoneEvents.forEach(function (eventType) { element.removeEventListener(eventType, sendActivationTrigger); element.addEventListener(eventType, sendActivationTrigger); }); $element.off('mouseenter', onMouseEnter); $element.on('mouseenter', onMouseEnter); OHIF.viewer.data.loadedSeriesData = layoutManager.viewportData; // Check if image plane (orientation / location) data is present for the current image var imagePlane = cornerstone.metaData.get('imagePlane', image.imageId); if (imagePlane && imagePlane.frameOfReferenceUID) { // If it is, add this element to the global synchronizer... OHIF.viewer.updateImageSynchronizer.add(element); if (OHIF.viewer.refLinesEnabled) { // ... and if reference lines are globally enabled, let cornerstoneTools know. cornerstoneTools.referenceLines.tool.enable(element, OHIF.viewer.updateImageSynchronizer); } // If the crosshairs tool is active, update the synchronizer // that is used for its synchronized viewport updating. // This is necessary if this new image shares a frame of reference // with currently displayed images if (activeTool === 'crosshairs') { updateCrosshairsSynchronizer(imagePlane.frameOfReferenceUID); } } // Set the active viewport based on the Session variable // This is done to ensure that the active element has the current // focus, so that keyboard events are triggered. if (viewportIndex === Session.get('activeViewport')) { var viewportContainer = $element.parents('.viewportContainer'); setActiveViewport(viewportContainer); } // Run any renderedCallback that exists in the data context if (data.renderedCallback && typeof data.renderedCallback === 'function') { data.renderedCallback(element); } // Check if it has after loadAndCacheImage callback if (typeof callbacks.after === 'function') { OHIF.log.info('imageViewerViewport after callback'); callbacks.after(image, templateData, element); } }, function (error) { // If something goes wrong while loading the image, fire the error handler. errorLoadingHandler(element, imageId, error); }); }; /** * This function sets the display set for the study and calls LoadDisplaySetIntoViewport function * * @param data includes study data * @param displaySetInstanceUid Display set information which is loaded in Template * @param templateData currentData of Template * */ var setDisplaySet = function (data, displaySetInstanceUid, templateData) { var study = data.study; if (!study) { throw new OHIFError('Study does not exist'); } var displaySets = study.displaySets; if (!displaySets.length) { displaySets = OHIF.viewerbase.sortingManager.getDisplaySets(study); study.displaySets = displaySets; study.setDisplaySets(displaySets); study.forEachDisplaySet(function (displaySet) { OHIF.viewerbase.stackManager.makeAndAddStack(study, displaySet); }); } if (!displaySets) { throw new OHIFError('Study has no display sets'); } displaySets.every(function (displaySet) { if (displaySet.displaySetInstanceUid === displaySetInstanceUid) { data.displaySet = displaySet; return false; } return true; }); // If we didn't find anything, stop here if (!data.displaySet) { data.displaySet = displaySets[0]; // throw new OHIFError('Display set not found in specified study!'); } // Otherwise, load pass the data object into loadSeriesIntoViewport loadDisplaySetIntoViewport(data, templateData); }; Meteor.startup(function () { window.ViewportLoading = window.ViewportLoading || {}; toolManager.configureLoadProcess(); }); Template.imageViewerViewport.onRendered(function () { var templateData = Template.currentData(); OHIF.log.info('imageViewerViewport onRendered'); // When the imageViewerViewport template is rendered var element = this.find('.imageViewerViewport'); this.element = element; this.$element = $(element); // Display the loading indicator for this element this.$element.siblings('.imageViewerLoadingIndicator').css('display', 'block'); // Get the current active viewport index, if this viewport has the same index, // add the CSS 'active' class to highlight this viewport. var activeViewport = Session.get('activeViewport'); // Focus the viewport if it's the active one if (templateData.viewportIndex === activeViewport) { this.$element.focus(); } var currentImageIdIndex = templateData.currentImageIdIndex; var viewport = templateData.viewport, studyInstanceUid = templateData.studyInstanceUid, seriesInstanceUid = templateData.seriesInstanceUid, renderedCallback = templateData.renderedCallback, displaySetInstanceUid = templateData.displaySetInstanceUid; if (!currentImageIdIndex) { currentImageIdIndex = 0; } // Calls extendData function to provide flexibility between systems imageViewerViewportData.extendData(templateData); // Create a data object to pass to the series loading function (loadSeriesIntoViewport) var data = { element: element, viewport: viewport, currentImageIdIndex: currentImageIdIndex, displaySetInstanceUid: displaySetInstanceUid, studyInstanceUid: studyInstanceUid, seriesInstanceUid: seriesInstanceUid, renderedCallback: renderedCallback, activeViewport: activeViewport }; // If no displaySetInstanceUid was supplied, display the drag/drop // instructions and then stop here since we don't know what to display in the viewport. if (!displaySetInstanceUid) { element.classList.add('empty'); this.$element.siblings('.imageViewerLoadingIndicator').css('display', 'none'); this.$element.siblings('.viewportInstructions').show(); return; } // @TypeSafeStudies var study = OHIF.viewer.Studies.findBy({ studyInstanceUid: studyInstanceUid }); data.study = study; setDisplaySet(data, displaySetInstanceUid, templateData); // Double click event handlers to handle viewport enlargement function doubleClickHandler(event) { var $element = $(this); var layoutManager = OHIF.viewerbase.layoutManager; var $viewports = $('.imageViewerViewport'); $element.trigger('ohif.viewer.viewport.toggleEnlargement'); // Get the double clicked viewport index var viewportIndex = $viewports.index(event.currentTarget); // Stop here if there's only one viewport if (!layoutManager.isZoomed && $viewports.length <= 1) return; // Enlarge the double clicked viewport layoutManager.toggleEnlargement(viewportIndex); // Wait for DOM re-rendering and update the active viewport Tracker.afterFlush(function () { var viewportIndexToZoom; // Check if the viewer is zoomed if (layoutManager.isZoomed) { // Set the active viewport as the only one visible viewportIndexToZoom = 0; } else { // Set the active viewport as the previous zoomed viewport viewportIndexToZoom = layoutManager.zoomedViewportIndex || 0; } // Set zoomed viewport as active... var viewportContainer = $('.viewportContainer').get(viewportIndexToZoom); setActiveViewport(viewportContainer); }); } var doubleClickEvents = ['cornerstonetoolsmousedoubleclick', 'cornerstonetoolsdoubletap']; doubleClickEvents.forEach(function (eventType) { element.removeEventListener(eventType, doubleClickHandler); element.addEventListener(eventType, doubleClickHandler); }); }); Template.imageViewerViewport.onDestroyed(function () { OHIF.log.info('imageViewerViewport onDestroyed'); // When a viewport element is being destroyed var element = this.find('.imageViewerViewport'); var $element = $(element); if (!element || $element.hasClass('empty') || !$element.find('canvas').length) { return; } // Disable mouse functions cornerstoneTools.mouseInput.disable(element); cornerstoneTools.touchInput.disable(element); cornerstoneTools.mouseWheelInput.disable(element); OHIF.viewer.updateImageSynchronizer.remove(element); // Clear the stack prefetch data var stackPrefetchData = cornerstoneTools.getToolState(element, 'stackPrefetch'); stackPrefetchData = []; cornerstoneTools.stackPrefetch.disable(element); // Try to stop any currently playing clips // Otherwise the interval will continuously throw errors try { var enabledElement = cornerstone.getEnabledElement(element); if (enabledElement) { cornerstoneTools.stopClip(element); } } catch (error) { OHIF.log.warn(error); } // Trigger custom Destroy Viewport event // for compatibility with other systems $element.trigger('OHIFDestroyedViewport'); // Disable the viewport element with Cornerstone // This also triggers the removal of the element from all available // synchronizers, such as the one used for reference lines. cornerstone.disable(element); }); Template.imageViewerViewport.events({ 'OHIFActivateViewport .imageViewerViewport': function (event) { OHIF.log.info('imageViewerViewport OHIFActivateViewport'); var viewportContainer = $(event.currentTarget).parents('.viewportContainer').get(0); setActiveViewport(viewportContainer); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"gridLayout":{"template.gridLayout.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/gridLayout/template.gridLayout.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("gridLayout"); Template["gridLayout"] = new Template("Template.gridLayout", (function() { var view = this; return HTML.DIV({ id: "imageViewerViewports" }, "\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(view.lookup("viewports")), _variable: "viewport" }; }, function() { return [ "\n ", HTML.DIV({ class: function() { return [ "viewportContainer ", Spacebars.mustache(view.lookup("getClass"), view.lookup("@index")), " ", Spacebars.mustache(view.lookup("activeClass"), view.lookup("@index")) ]; }, style: function() { return [ "height:", Spacebars.mustache(view.lookup("height")), "%;width:", Spacebars.mustache(view.lookup("width")), "%;" ]; } }, "\n ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("eq"), Spacebars.dot(view.lookup("viewport"), "plugin"), "cornerstone"); }, function() { return [ "\n ", HTML.DIV({ class: "removable" }, "\n ", Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("clone"), view.lookup("viewport")); }, function() { return Spacebars.include(view.lookupTemplate("imageViewerViewport")); }), "\n "), "\n " ]; }, function() { return [ "\n ", HTML.DIV({ class: function() { return [ "viewport-plugin-", Spacebars.mustache(Spacebars.dot(view.lookup("viewport"), "plugin")) ]; }, style: "height:100%; width: 100%" }, "\n "), "\n " ]; }), "\n ", Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("clone"), view.lookup("."), Spacebars.kw({ viewport: view.lookup("viewport"), viewportIndex: view.lookup("@index") })); }, function() { return Spacebars.include(view.lookupTemplate("seriesQuickSwitch")); }), "\n "), "\n " ]; }), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"gridLayout.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/gridLayout/gridLayout.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 1); var TOP_CLASS = 'top'; var BOTTOM_CLASS = 'bottom'; var MIDDLE_CLASS = 'middle'; Template.gridLayout.helpers({ // Get the height percentage for each viewport height: function () { var instance = Template.instance(); var rows = instance.data.rows || 1; return 100 / rows; }, // Get the width percentage for each viewport width: function () { var instance = Template.instance(); var columns = instance.data.columns || 1; return 100 / columns; }, // Get class for each viewport, so each app // using ohif-viewerbase can style on their own getClass: function (index) { var rows = this.rows, columns = this.columns; if (rows === 1) { return TOP_CLASS + " " + BOTTOM_CLASS; } var actualRow = Math.floor(index / columns); if (actualRow === 0) { return TOP_CLASS; } if (actualRow + 1 === rows) { return BOTTOM_CLASS; } return MIDDLE_CLASS; }, activeClass: function (index) { if (Session.get('activeViewport') === index) { return 'active'; } ; }, // Return the viewports list viewports: function () { var instance = Template.instance(); var rows = instance.data.rows; var columns = instance.data.columns; var numViewports = rows * columns; var viewportData = instance.data.viewportData; var numViewportsWithData = viewportData.length; // Check if the viewportData length is different from the given if (numViewportsWithData < numViewports) { // Add the missing viewports var difference = numViewports - numViewportsWithData; for (var i = 0; i < difference; i++) { viewportData.push({ viewportIndex: numViewportsWithData + i + 1, rows: rows, columns: columns }); } } else if (numViewportsWithData > numViewports) { // Remove the additional viewports return viewportData.slice(0, numViewports); } // Return the viewports return viewportData; } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"loadingIndicator":{"template.loadingIndicator.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/loadingIndicator/template.loadingIndicator.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("loadingIndicator"); Template["loadingIndicator"] = new Template("Template.loadingIndicator", (function() { var view = this; return [ HTML.DIV({ class: "imageViewerLoadingIndicator loadingIndicator" }, "\n ", HTML.DIV({ class: "indicatorContents" }, "\n ", HTML.P("Loading... ", HTML.Raw(''), " ", Blaze.View("lookup:percentComplete", function() { return Spacebars.mustache(view.lookup("percentComplete")); })), "\n "), "\n "), HTML.Raw('\n
\n
\n

Error Loading Image

\n

An error has occurred.

\n

\n
\n
') ]; })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"loadingIndicator.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/loadingIndicator/loadingIndicator.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 1); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 2); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 3); Meteor.startup(function () { // This checking is necessary because cornerstoneTools may not have some tools available. // Example: when an app defines its own cornerstone's lib versions, so it // uses only ohif-viewerbase and not ohif-cornerstone and those libs are added later. if (cornerstoneTools.loadHandlerManager) { cornerstoneTools.loadHandlerManager.setStartLoadHandler(startLoadingHandler); cornerstoneTools.loadHandlerManager.setEndLoadHandler(doneLoadingHandler); cornerstoneTools.loadHandlerManager.setErrorLoadingHandler(errorLoadingHandler); } }); var loadHandlerTimeout; var startLoadingHandler = function (element) { clearTimeout(loadHandlerTimeout); loadHandlerTimeout = setTimeout(function () { console.log('startLoading'); var elem = $(element); elem.siblings('.imageViewerErrorLoadingIndicator').css('display', 'none'); elem.find('canvas').not('.magnifyTool').addClass('faded'); elem.siblings('.imageViewerLoadingIndicator').css('display', 'block'); }, OHIF.viewer.loadIndicatorDelay); }; var doneLoadingHandler = function (element) { clearTimeout(loadHandlerTimeout); var elem = $(element); elem.siblings('.imageViewerErrorLoadingIndicator').css('display', 'none'); elem.find('canvas').not('.magnifyTool').removeClass('faded'); elem.siblings('.imageViewerLoadingIndicator').css('display', 'none'); }; var errorLoadingHandler = function (element, imageId, error, source) { clearTimeout(loadHandlerTimeout); var elem = $(element); // Could probably chain all of these, but this is more readable elem.find('canvas').not('.magnifyTool').removeClass('faded'); elem.siblings('.imageViewerLoadingIndicator').css('display', 'none'); // Don't display errors from the stackPrefetch tool if (source === 'stackPrefetch') { return; } var errorLoadingIndicator = elem.siblings('.imageViewerErrorLoadingIndicator'); errorLoadingIndicator.css('display', 'block'); // This is just used to expand upon some error messages that are sent // when things fail. An example is a network error throwing the error // which is only described as "network". var errorDetails = { network: 'A network error has occurred' // We need to expand this further when we see more obscure error messages }; if (errorDetails.hasOwnProperty(error)) { error = errorDetails[error]; } errorLoadingIndicator.find('.description').text("An error has occurred while loading image: " + imageId); if (error) { errorLoadingIndicator.find('.details').text("Details: " + error); } }; Template.loadingIndicator.helpers({ 'percentComplete': function () { var percentComplete = Session.get('CornerstoneLoadProgress' + this.viewportIndex); if (percentComplete && percentComplete !== 100) { return percentComplete + "%"; } } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"annotationDialogs":{"template.annotationDialogs.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/annotationDialogs/template.annotationDialogs.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("annotationDialogs"); Template["annotationDialogs"] = new Template("Template.annotationDialogs", (function() { var view = this; return [ HTML.getTag("dialog")({ id: "annotationDialog", class: "annotationDialog noselect" }, "\n ", HTML.H5("Enter your annotation"), "\n ", HTML.DIV({ class: "annotationTextInputOptions" }, "\n ", HTML.LABEL({ for: "annotationTextInput" }, "New label"), "\n ", HTML.INPUT({ name: "annotationTextInput", class: "annotationTextInput", type: "text", tabindex: "-1", autocomplete: "off" }), "\n "), "\n ", HTML.A({ class: "annotationDialogConfirm btn btn-sm btn-primary" }, "OK"), "\n "), "\n\n ", HTML.getTag("dialog")({ id: "relabelAnnotationDialog", class: "annotationDialog noselect", oncontextmenu: "return false" }, "\n ", HTML.H5("Edit your annotation"), "\n ", HTML.DIV({ class: "annotationTextInputOptions" }, "\n ", HTML.LABEL({ for: "annotationTextInput" }, "New label"), "\n ", HTML.INPUT({ name: "annotationTextInput", class: "annotationTextInput", type: "text", tabindex: "-1", autocomplete: "off" }), "\n "), "\n ", HTML.DIV("\n ", HTML.A({ class: "relabelRemove btn btn-sm btn-secondary" }, "Remove marker"), "\n ", HTML.A({ class: "relabelConfirm btn btn-sm btn-primary" }, "OK"), "\n "), "\n ") ]; })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"annotationDialogs.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/annotationDialogs/annotationDialogs.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.annotationDialogs.onRendered(function () { var instance = Template.instance(); var dialogIds = ['annotationDialog', 'relabelAnnotationDialog']; dialogIds.forEach(function (id) { var dialog = instance.$('#' + id); dialog.draggable(); dialogPolyfill.registerDialog(dialog.get(0)); }); }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"viewportOrientationMarkers":{"template.viewportOrientationMarkers.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/viewportOrientationMarkers/template.viewportOrientationMarkers.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("viewportOrientationMarkers"); Template["viewportOrientationMarkers"] = new Template("Template.viewportOrientationMarkers", (function() { var view = this; return HTML.Raw('
\n
\n
\n
\n
\n
'); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"viewportOverlay":{"template.viewportOverlay.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/viewportOverlay/template.viewportOverlay.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("viewportOverlay"); Template["viewportOverlay"] = new Template("Template.viewportOverlay", (function() { var view = this; return HTML.DIV({ class: function() { return [ "imageViewerViewportOverlay noselect ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("gt"), view.lookup("numImages"), 1); }, function() { return "controlsVisible"; }) ]; } }, "\n ", Blaze.Unless(function() { return Spacebars.call(view.lookup("tagDisplaySpecified")); }, function() { return [ "\n ", HTML.DIV({ class: "topleft dicomTag" }, "\n ", HTML.DIV(Blaze.View("lookup:formatPN", function() { return Spacebars.mustache(view.lookup("formatPN"), view.lookup("patientName")); })), "\n ", HTML.DIV(Blaze.View("lookup:patientId", function() { return Spacebars.mustache(view.lookup("patientId")); })), "\n ", HTML.DIV({ class: "priorIndicator" }, Blaze.View("lookup:prior", function() { return Spacebars.mustache(view.lookup("prior")); })), "\n "), "\n ", HTML.DIV({ class: "topright dicomTag" }, "\n ", HTML.DIV(Blaze.View("lookup:studyDescription", function() { return Spacebars.mustache(view.lookup("studyDescription")); })), "\n ", HTML.DIV(Blaze.View("lookup:formatDA", function() { return Spacebars.mustache(view.lookup("formatDA"), view.lookup("studyDate")); }), " ", Blaze.View("lookup:formatTM", function() { return Spacebars.mustache(view.lookup("formatTM"), view.lookup("studyTime")); })), "\n "), "\n ", HTML.DIV({ class: "bottomright dicomTag" }, "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.call(view.lookup("zoom")); }, function() { return [ "Zoom: ", Blaze.View("lookup:formatNumberPrecision", function() { return Spacebars.mustache(view.lookup("formatNumberPrecision"), view.lookup("zoom"), 0); }), "%" ]; })), "\n ", HTML.DIV({ class: "compressionIndicator" }, Blaze.View("lookup:compression", function() { return Spacebars.mustache(view.lookup("compression")); })), "\n ", HTML.DIV(Blaze.View("lookup:wwwc", function() { return Spacebars.mustache(view.lookup("wwwc")); })), "\n "), "\n ", HTML.DIV({ class: "bottomleft dicomTag" }, "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.call(view.lookup("seriesNumber")); }, function() { return [ "Ser: ", Blaze.View("lookup:seriesNumber", function() { return Spacebars.mustache(view.lookup("seriesNumber")); }) ]; })), "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.dataMustache(view.lookup("gt"), view.lookup("numImages"), 1); }, function() { return [ "Img: ", Blaze.View("lookup:instanceNumber", function() { return Spacebars.mustache(view.lookup("instanceNumber")); }), " (", Blaze.View("lookup:imageIndex", function() { return Spacebars.mustache(view.lookup("imageIndex")); }), "/", Blaze.View("lookup:numImages", function() { return Spacebars.mustache(view.lookup("numImages")); }), ")" ]; })), "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.call(view.lookup("frameRate")); }, function() { return [ Blaze.View("lookup:formatNumberPrecision", function() { return Spacebars.mustache(view.lookup("formatNumberPrecision"), view.lookup("frameRate"), 2); }), " FPS" ]; })), "\n ", HTML.DIV(Blaze.View("lookup:imageDimensions", function() { return Spacebars.mustache(view.lookup("imageDimensions")); })), "\n ", HTML.DIV("\n ", HTML.SPAN(Blaze.If(function() { return Spacebars.dataMustache(view.lookup("isValidNumber"), view.lookup("location")); }, function() { return [ "Loc: ", Blaze.View("lookup:formatNumberPrecision", function() { return Spacebars.mustache(view.lookup("formatNumberPrecision"), view.lookup("location"), 2); }), " mm" ]; })), "\n ", HTML.SPAN(Blaze.If(function() { return Spacebars.call(view.lookup("thickness")); }, function() { return [ "Thick: ", Blaze.View("lookup:formatNumberPrecision", function() { return Spacebars.mustache(view.lookup("formatNumberPrecision"), view.lookup("thickness"), 2); }), " mm" ]; })), "\n ", HTML.SPAN(Blaze.If(function() { return Spacebars.call(view.lookup("spacingBetweenSlices")); }, function() { return [ "Spacing: ", Blaze.View("lookup:formatNumberPrecision", function() { return Spacebars.mustache(view.lookup("formatNumberPrecision"), view.lookup("spacingBetweenSlices"), 2); }), " mm" ]; })), "\n "), "\n ", HTML.DIV(Blaze.View("lookup:seriesDescription", function() { return Spacebars.mustache(view.lookup("seriesDescription")); })), "\n "), "\n " ]; }), "\n\n ", Blaze.If(function() { return Spacebars.call(view.lookup("tagDisplayRightOnly")); }, function() { return [ "\n ", HTML.DIV({ class: "topright dicomTag" }, "\n ", HTML.DIV(Blaze.View("lookup:formatPN", function() { return Spacebars.mustache(view.lookup("formatPN"), view.lookup("patientName")); })), "\n ", HTML.DIV(Blaze.View("lookup:patientId", function() { return Spacebars.mustache(view.lookup("patientId")); })), "\n ", HTML.DIV({ class: "priorIndicator" }, Blaze.View("lookup:prior", function() { return Spacebars.mustache(view.lookup("prior")); })), "\n ", HTML.DIV(Blaze.View("lookup:studyDescription", function() { return Spacebars.mustache(view.lookup("studyDescription")); })), "\n ", HTML.DIV(Blaze.View("lookup:formatDA", function() { return Spacebars.mustache(view.lookup("formatDA"), view.lookup("studyDate")); }), " ", Blaze.View("lookup:formatTM", function() { return Spacebars.mustache(view.lookup("formatTM"), view.lookup("studyTime")); })), "\n "), "\n ", HTML.DIV({ class: "bottomright dicomTag" }, "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.call(view.lookup("seriesNumber")); }, function() { return [ "Ser: ", Blaze.View("lookup:seriesNumber", function() { return Spacebars.mustache(view.lookup("seriesNumber")); }) ]; })), "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.dataMustache(view.lookup("gt"), view.lookup("numImages"), 1); }, function() { return [ "Img: ", Blaze.View("lookup:instanceNumber", function() { return Spacebars.mustache(view.lookup("instanceNumber")); }), " (", Blaze.View("lookup:imageIndex", function() { return Spacebars.mustache(view.lookup("imageIndex")); }), "/", Blaze.View("lookup:numImages", function() { return Spacebars.mustache(view.lookup("numImages")); }), ")" ]; })), "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.call(view.lookup("frameRate")); }, function() { return [ Blaze.View("lookup:formatNumberPrecision", function() { return Spacebars.mustache(view.lookup("formatNumberPrecision"), view.lookup("frameRate"), 2); }), " FPS" ]; })), "\n ", HTML.DIV(Blaze.View("lookup:imageDimensions", function() { return Spacebars.mustache(view.lookup("imageDimensions")); })), "\n ", HTML.DIV(Blaze.View("lookup:seriesDescription", function() { return Spacebars.mustache(view.lookup("seriesDescription")); })), "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.call(view.lookup("zoom")); }, function() { return [ "Zoom: ", Blaze.View("lookup:formatNumberPrecision", function() { return Spacebars.mustache(view.lookup("formatNumberPrecision"), view.lookup("zoom"), 0); }), "%" ]; })), "\n ", HTML.DIV({ class: "compressionIndicator" }, Blaze.View("lookup:compression", function() { return Spacebars.mustache(view.lookup("compression")); })), "\n ", HTML.DIV(Blaze.View("lookup:wwwc", function() { return Spacebars.mustache(view.lookup("wwwc")); })), "\n "), "\n " ]; }), "\n\n ", Blaze.If(function() { return Spacebars.call(view.lookup("tagDisplayLeftOnly")); }, function() { return [ "\n ", HTML.DIV({ class: "topleft dicomTag" }, "\n ", HTML.DIV(Blaze.View("lookup:formatPN", function() { return Spacebars.mustache(view.lookup("formatPN"), view.lookup("patientName")); })), "\n ", HTML.DIV(Blaze.View("lookup:patientId", function() { return Spacebars.mustache(view.lookup("patientId")); })), "\n ", HTML.DIV({ class: "priorIndicator" }, Blaze.View("lookup:prior", function() { return Spacebars.mustache(view.lookup("prior")); })), "\n ", HTML.DIV(Blaze.View("lookup:studyDescription", function() { return Spacebars.mustache(view.lookup("studyDescription")); })), "\n ", HTML.DIV(Blaze.View("lookup:formatDA", function() { return Spacebars.mustache(view.lookup("formatDA"), view.lookup("studyDate")); }), " ", Blaze.View("lookup:formatTM", function() { return Spacebars.mustache(view.lookup("formatTM"), view.lookup("studyTime")); })), "\n "), "\n ", HTML.DIV({ class: "bottomleft dicomTag" }, "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.call(view.lookup("seriesNumber")); }, function() { return [ "Ser: ", Blaze.View("lookup:seriesNumber", function() { return Spacebars.mustache(view.lookup("seriesNumber")); }) ]; })), "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.dataMustache(view.lookup("gt"), view.lookup("numImages"), 1); }, function() { return [ "Img: ", Blaze.View("lookup:instanceNumber", function() { return Spacebars.mustache(view.lookup("instanceNumber")); }), " (", Blaze.View("lookup:imageIndex", function() { return Spacebars.mustache(view.lookup("imageIndex")); }), "/", Blaze.View("lookup:numImages", function() { return Spacebars.mustache(view.lookup("numImages")); }), ")" ]; })), "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.call(view.lookup("frameRate")); }, function() { return [ Blaze.View("lookup:formatNumberPrecision", function() { return Spacebars.mustache(view.lookup("formatNumberPrecision"), view.lookup("frameRate"), 2); }), " FPS" ]; })), "\n ", HTML.DIV(Blaze.View("lookup:imageDimensions", function() { return Spacebars.mustache(view.lookup("imageDimensions")); })), "\n ", HTML.DIV(Blaze.View("lookup:seriesDescription", function() { return Spacebars.mustache(view.lookup("seriesDescription")); })), "\n ", HTML.DIV(Blaze.If(function() { return Spacebars.call(view.lookup("zoom")); }, function() { return [ "Zoom: ", Blaze.View("lookup:formatNumberPrecision", function() { return Spacebars.mustache(view.lookup("formatNumberPrecision"), view.lookup("zoom"), 0); }), "%" ]; })), "\n ", HTML.DIV({ class: "compressionIndicator" }, Blaze.View("lookup:compression", function() { return Spacebars.mustache(view.lookup("compression")); })), "\n ", HTML.DIV(Blaze.View("lookup:wwwc", function() { return Spacebars.mustache(view.lookup("wwwc")); })), "\n "), "\n " ]; }), "\n\n ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("gt"), view.lookup("numImages"), 1); }, function() { return [ "\n ", Blaze._TemplateWith(function() { return { imageIndex: Spacebars.call(view.lookup("imageIndex")), numImages: Spacebars.call(view.lookup("numImages")) }; }, function() { return Spacebars.include(view.lookupTemplate("imageControls")); }), "\n " ]; }), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"viewportOverlay.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 1); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 2); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 3); var cornerstone; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; } }, 4); var viewportOverlayUtils; module.watch(require("../../../lib/viewportOverlayUtils"), { viewportOverlayUtils: function (v) { viewportOverlayUtils = v; } }, 5); var getElementIfNotEmpty; module.watch(require("../../../lib/getElementIfNotEmpty"), { getElementIfNotEmpty: function (v) { getElementIfNotEmpty = v; } }, 6); var getStackDataIfNotEmpty; module.watch(require("../../../lib/getStackDataIfNotEmpty"), { getStackDataIfNotEmpty: function (v) { getStackDataIfNotEmpty = v; } }, 7); Template.viewportOverlay.onCreated(function () { var instance = Template.instance(); instance.getImageIndex = function () { var stack = getStackDataIfNotEmpty(instance.data.viewportIndex); if (!stack || stack.currentImageIdIndex === undefined) return; return stack.currentImageIdIndex; }; }); Template.viewportOverlay.helpers({ wwwc: function () { Session.get('CornerstoneImageRendered' + this.viewportIndex); var element = getElementIfNotEmpty(this.viewportIndex); if (!element) { return ''; } var viewport = cornerstone.getViewport(element); if (!viewport) { return ''; } return 'W ' + viewport.voi.windowWidth.toFixed(0) + ' L ' + viewport.voi.windowCenter.toFixed(0); }, zoom: function () { Session.get('CornerstoneImageRendered' + this.viewportIndex); var element = getElementIfNotEmpty(this.viewportIndex); if (!element) { return; } var viewport = cornerstone.getViewport(element); if (!viewport) { return; } return viewport.scale * 100.0; }, imageDimensions: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); var image = viewportOverlayUtils.getImage(this.viewportIndex); if (!image) { return ''; } return image.width + ' x ' + image.height; }, patientName: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getPatient.call(this, 'name'); }, patientId: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getPatient.call(this, 'id'); }, patientBirthDate: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getPatient.call(this, 'birthDate'); }, patientSex: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getPatient.call(this, 'sex'); }, studyDate: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getStudy.call(this, 'studyDate'); }, studyTime: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getStudy.call(this, 'studyTime'); }, studyDescription: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getStudy.call(this, 'studyDescription'); }, seriesDescription: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getSeries.call(this, 'seriesDescription'); }, frameRate: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); var frameTime = viewportOverlayUtils.getInstance.call(this, 'frameTime'); if (!frameTime) { return; } var frameRate = 1000 / frameTime; return frameRate.toFixed(1); }, seriesNumber: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getSeries.call(this, 'seriesNumber'); }, instanceNumber: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getInstance.call(this, 'instanceNumber'); }, thickness: function () { // Displays Slice Thickness (0018,0050) Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getInstance.call(this, 'sliceThickness'); }, location: function () { // Displays Slice Location (0020,1041), if present. // - Otherwise, displays Table Position (0018,9327) // - TODO: Otherwise, displays a value derived from Image Position (Patient) (0020,0032) Session.get('CornerstoneNewImage' + this.viewportIndex); var sliceLocation = viewportOverlayUtils.getInstance.call(this, 'sliceLocation'); if (sliceLocation !== '') { return sliceLocation; } var tablePosition = viewportOverlayUtils.getInstance.call(this, 'tablePosition'); if (tablePosition !== '') { return tablePosition; } return viewportOverlayUtils.getInstance.call(this, 'imagePositionPatient'); }, spacingBetweenSlices: function () { // Displays Spacing Between Slices (0018,0088), if present. // TODO: Otherwise, displays a value derived from successive values // of Image Position (Patient) (0020,0032) perpendicular to // the Image Orientation (Patient) (0020,0037) Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getInstance.call(this, 'spacingBetweenSlices'); }, compression: function () { // Displays whether or not lossy compression has been applied: // // - Checks Lossy Image Compression (0028,2110) // - If so, displays the value of Lossy Image Compression Ratio (0028,2112) // and Lossy Image Compression Method (0028,2114) Session.get('CornerstoneNewImage' + this.viewportIndex); if (!this.imageId) { return false; } var instance = cornerstone.metaData.get('instance', this.imageId); if (!instance) { return ''; } if (instance.lossyImageCompression === '01' && instance.lossyImageCompressionRatio !== '') { var compressionMethod = instance.lossyImageCompressionMethod || 'Lossy: '; var compressionRatio = parseFloat(instance.lossyImageCompressionRatio).toFixed(2); return compressionMethod + compressionRatio + ' : 1'; } return 'Lossless / Uncompressed'; }, tagDisplayLeftOnly: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getTagDisplay.call(this, 'side') === 'L'; }, tagDisplayRightOnly: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getTagDisplay.call(this, 'side') === 'R'; }, tagDisplaySpecified: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getTagDisplay.call(this, 'side'); }, imageNumber: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); return viewportOverlayUtils.getInstance.call(this, 'number'); }, imageIndex: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); var imageIndex = Template.instance().getImageIndex(); return _.isUndefined(imageIndex) ? 0 : imageIndex + 1; }, numImages: function () { Session.get('CornerstoneNewImage' + this.viewportIndex); var stack = getStackDataIfNotEmpty(this.viewportIndex); if (!stack || !stack.imageIds) { return; } return stack.imageIds.length; }, prior: function () { // This helper is updated whenever a new image is displayed in the viewport Session.get('CornerstoneNewImage' + this.viewportIndex); if (!this.imageId) { return; } // @TypeSafeStudies // Make sure there are more than two studies loaded in the viewer var viewportStudies = OHIF.viewer.Studies.all(); if (viewportStudies.length < 2) { return; } // Here we sort the collection in ascending order by study date, so // that we can obtain the oldest study as the first element of the array // // TODO= Find out if we should encode studyDate as a Date in the OHIF.viewer.Studies Collection var viewportStudiesArray = _.sortBy(viewportStudies, function (study) { return viewportOverlayUtils.formatDateTime(study.studyDate, study.studyTime); }); // Get study data var study = cornerstone.metaData.get('study', this.imageId); if (!study) { return; } var oldestStudy = viewportStudiesArray[0]; if (viewportOverlayUtils.formatDateTime(study.studyDate, study.studyTime) <= viewportOverlayUtils.formatDateTime(oldestStudy.studyDate, oldestStudy.studyTime)) { return 'Prior'; } } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"viewerMain":{"template.viewerMain.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/viewerMain/template.viewerMain.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("viewerMain"); Template["viewerMain"] = new Template("Template.viewerMain", (function() { var view = this; return HTML.Raw('
\n
\n
\n
'); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"viewerMain.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/viewerMain/viewerMain.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 1); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 2); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 3); var unloadHandlers; module.watch(require("../../../lib/unloadHandlers"), { unloadHandlers: function (v) { unloadHandlers = v; } }, 4); var ResizeViewportManager; module.watch(require("../../../lib/classes/ResizeViewportManager"), { ResizeViewportManager: function (v) { ResizeViewportManager = v; } }, 5); var LayoutManager; module.watch(require("../../../lib/classes/LayoutManager"), { LayoutManager: function (v) { LayoutManager = v; } }, 6); var StudyPrefetcher; module.watch(require("../../../lib/classes/StudyPrefetcher"), { StudyPrefetcher: function (v) { StudyPrefetcher = v; } }, 7); var StudyLoadingListener; module.watch(require("../../../lib/classes/StudyLoadingListener"), { StudyLoadingListener: function (v) { StudyLoadingListener = v; } }, 8); Meteor.startup(function () { window.ResizeViewportManager = window.ResizeViewportManager || new ResizeViewportManager(); // Set initial value for OHIFViewerMainRendered // session variable. This can used in viewer main template Session.set('OHIFViewerMainRendered', false); }); Template.viewerMain.onCreated(function () { // Attach the Window resize listener // Don't use jQuery here. "window.onresize" will always be null // If its necessary, check all the code for window.onresize getter // and change it to jQuery._data(window, 'events')['resize']. // Otherwise this function will be probably overrided. // See cineDialog instance.setResizeHandler function window.addEventListener('resize', window.ResizeViewportManager.getResizeHandler()); // Add beforeUnload event handler to check for unsaved changes window.addEventListener('beforeunload', unloadHandlers.beforeUnload); }); Template.viewerMain.onRendered(function () { var instance = Template.instance(); var studies = instance.data.studies; var parentElement = instance.$('#layoutManagerTarget').get(0); var studyPrefetcher = StudyPrefetcher.getInstance(); instance.studyPrefetcher = studyPrefetcher; instance.studyLoadingListener = StudyLoadingListener.getInstance(); instance.studyLoadingListener.clear(); instance.studyLoadingListener.addStudies(studies); OHIF.viewerbase.layoutManager = new LayoutManager(parentElement, studies); studyPrefetcher.setStudies(studies); Session.set('OHIFViewerMainRendered', Math.random()); }); Template.viewerMain.onDestroyed(function () { var instance = Template.instance(); OHIF.log.info('viewerMain onDestroyed'); // Remove the Window resize listener window.removeEventListener('resize', window.ResizeViewportManager.getResizeHandler()); // Remove beforeUnload event handler... window.removeEventListener('beforeunload', unloadHandlers.beforeUnload); // Destroy the synchronizer used to update reference lines OHIF.viewer.updateImageSynchronizer.destroy(); delete OHIF.viewerbase.layoutManager; ProtocolEngine = null; Session.set('OHIFViewerMainRendered', false); // Stop prefetching when we close the viewer instance.studyPrefetcher.destroy(); // Destroy stack loading listeners when we close the viewer instance.studyLoadingListener.clear(); // Clear references to all stacks in the StackManager OHIF.viewerbase.stackManager.clearStacks(); // @TypeSafeStudies // Clears OHIF.viewer.Studies collection OHIF.viewer.Studies.removeAll(); // @TypeSafeStudies // Clears OHIF.viewer.StudyMetadataList collection OHIF.viewer.StudyMetadataList.removeAll(); }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"toolContextMenu":{"toolContextMenu.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/toolContextMenu/toolContextMenu.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 1); var cornerstone, cornerstoneTools; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; }, cornerstoneTools: function (v) { cornerstoneTools = v; } }, 2); var toolManager; module.watch(require("../../../lib/toolManager"), { toolManager: function (v) { toolManager = v; } }, 3); var toolTypes = ['length', 'simpleAngle', 'probe', 'ellipticalRoi', 'rectangleRoi', 'arrowAnnotate']; var TypeToLabelMap = { length: 'Length', simpleAngle: 'Angle', probe: 'Probe', ellipticalRoi: 'Elliptical ROI', rectangleRoi: 'Rectangle ROI', arrowAnnotate: 'Annotation' }; var dropdownItems = [{ actionType: 'Delete', action: function (_ref) { var nearbyToolData = _ref.nearbyToolData, eventData = _ref.eventData; var element = eventData.element; cornerstoneTools.removeToolState(element, nearbyToolData.toolType, nearbyToolData.tool); cornerstone.updateImage(element); } }]; var getTypeText = function (toolData, actionType) { var toolType = toolData.toolType; var message = "" + TypeToLabelMap[toolType]; if (toolType === 'arrowAnnotate') { message = message + " \"" + toolData.tool.text + "\""; } return actionType + " " + message; }; var createDropdown = function (eventData) { var isTouchEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var nearbyToolData = toolManager.getNearbyToolData(eventData.element, eventData.currentPoints.canvas, toolTypes); // Annotate tools for touch events already have a press handle to edit it, has a better UX for deleting it if (isTouchEvent && nearbyToolData.toolType === 'arrowAnnotate') return; if (nearbyToolData) { dropdownItems.forEach(function (item) { item.params = { eventData: eventData, nearbyToolData: nearbyToolData }; item.text = getTypeText(nearbyToolData, item.actionType); }); OHIF.ui.showDropdown(dropdownItems, { menuClasses: 'dropdown-menu-left', event: eventData.event }); } }; Template.viewerMain.events({ 'cornerstonetoolsmouseclick .imageViewerViewport': function (event) { var originalEvent = event.originalEvent; var eventData = originalEvent.detail; if (eventData.which === 3) { createDropdown(eventData); } }, 'cornerstonetoolstouchpress .imageViewerViewport': function (event) { var originalEvent = event.originalEvent; var eventData = originalEvent.detail; createDropdown(eventData, true); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"imageControls":{"template.imageControls.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/imageControls/template.imageControls.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("imageControls"); Template["imageControls"] = new Template("Template.imageControls", (function() { var view = this; return HTML.DIV({ class: "imageControls" }, "\n ", HTML.DIV({ class: "scrollbar" }, "\n ", HTML.INPUT({ class: "imageSlider", type: "range", min: "1", value: function() { return Spacebars.mustache(view.lookup("imageIndex")); }, max: function() { return Spacebars.mustache(view.lookup("numImages")); } }), "\n "), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"imageControls.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/imageControls/imageControls.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 1); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 2); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 3); var setActiveViewport; module.watch(require("../../../lib/setActiveViewport"), { setActiveViewport: function (v) { setActiveViewport = v; } }, 4); var switchToImageByIndex; module.watch(require("../../../lib/switchToImageByIndex"), { switchToImageByIndex: function (v) { switchToImageByIndex = v; } }, 5); var slideTimeoutTime = 40; var slideTimeout; Template.imageControls.onRendered(function () { var instance = Template.instance(); // Set the current imageSlider width to its parent's height // (because webkit is stupid and can't style vertical sliders) var $slider = instance.$('.imageSlider'); var $viewport = $slider.closest('.imageViewerViewportOverlay').siblings('.imageViewerViewport'); instance.handleResize = _.throttle(function () { var viewportHeight = $viewport.height(); $slider.width(viewportHeight - 20); }, 150); instance.handleResize(); $(window).on('resize', instance.handleResize); }); Template.imageControls.onDestroyed(function () { var instance = Template.instance(); if (instance.handleResize) { $(window).off('resize', instance.handleResize); } }); Template.imageControls.events({ 'rescale .scrollbar': function (event, instance) { instance.handleResize(); }, 'keydown input[type=range]': function (event) { // We don't allow direct keyboard up/down input on the // image sliders since the natural direction is reversed (0 is at the top) // Store the KeyCodes in an object for readability var keys = { DOWN: 40, UP: 38 }; if (event.which === keys.DOWN) { OHIF.commands.run('scrollDown'); event.preventDefault(); } else if (event.which === keys.UP) { OHIF.commands.run('scrollUp'); event.preventDefault(); } }, 'input input[type=range], change input[type=range]': function (event) { // Note that we throttle requests to prevent the // user's ultrafast scrolling from firing requests too quickly. clearTimeout(slideTimeout); slideTimeout = setTimeout(function () { // Using the slider in an inactive viewport // should cause that viewport to become active var $slider = $(event.currentTarget); var viewportContainer = $slider.parents('.viewportContainer'); setActiveViewport(viewportContainer); // Subtract 1 here since the slider goes from 1 to N images // But the stack indexing starts at 0 var newImageIdIndex = parseInt($slider.val(), 10) - 1; switchToImageByIndex(newImageIdIndex); }, slideTimeoutTime); return false; } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"layoutButton":{"template.layoutButton.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/layoutButton/template.layoutButton.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("layoutButton"); Template["layoutButton"] = new Template("Template.layoutButton", (function() { var view = this; return HTML.DIV({ id: function() { return Spacebars.mustache(Spacebars.dot(view.lookup("."), "id")); }, class: function() { return [ "toolbarSectionButton rp-x-1 ", Spacebars.mustache(Spacebars.dot(view.lookup("."), "classes")), " ", Spacebars.mustache(view.lookup("activeClass")), " js-dropdown-toggle" ]; }, title: function() { return Spacebars.mustache(Spacebars.dot(view.lookup("."), "title")); }, "data-target": "#layoutChooser" }, "\n ", HTML.DIV({ class: "svgContainer" }, "\n ", Blaze.If(function() { return Spacebars.call(Spacebars.dot(view.lookup("."), "svgLink")); }, function() { return [ "\n ", HTML.SVG("\n ", HTML.USE({ "xlink:href": function() { return Spacebars.mustache(view.lookup("absoluteUrl"), Spacebars.dot(view.lookup("."), "svgLink")); } }), "\n "), "\n " ]; }, function() { return [ "\n ", HTML.I({ class: function() { return Spacebars.mustache(view.lookup("iconClasses")); } }), "\n " ]; }), "\n "), "\n ", HTML.DIV({ class: "buttonLabel" }, "\n ", Blaze.View("lookup:..title", function() { return Spacebars.mustache(Spacebars.dot(view.lookup("."), "title")); }), "\n "), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"layoutButton.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/layoutButton/layoutButton.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 1); var viewportUtils; module.watch(require("../../../lib/viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 2); Template.layoutButton.events({ // TODO: Check why 'click' event won't fire? 'mousedown .js-dropdown-toggle': function (event) { // Select the button and it's target dropdown menu var $button = $(event.currentTarget); var $dropdown = $($button.data('target')); // Adjust the dropdown's CSS to properly place it on the page $dropdown.css({ top: $button.offset().top + $button.outerHeight() + 'px', left: $button.offset().left + 'px' }); // Open or close the layout chooser dialog viewportUtils.toggleDialog($dropdown); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"layoutChooser":{"template.layoutChooser.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/layoutChooser/template.layoutChooser.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("layoutChooser"); Template["layoutChooser"] = new Template("Template.layoutChooser", (function() { var view = this; return HTML.DIV({ id: "layoutChooser", class: "layoutChooser dialog-animated" }, "\n ", HTML.TABLE("\n ", HTML.TR("\n ", HTML.TD(), "\n ", HTML.TD(), "\n ", HTML.TD(), "\n ", HTML.TD(), "\n "), "\n ", HTML.TR("\n ", HTML.TD(), "\n ", HTML.TD(), "\n ", HTML.TD(), "\n ", HTML.TD(), "\n "), "\n ", HTML.TR("\n ", HTML.TD(), "\n ", HTML.TD(), "\n ", HTML.TD(), "\n ", HTML.TD(), "\n "), "\n ", HTML.TR("\n ", HTML.TD(), "\n ", HTML.TD(), "\n ", HTML.TD(), "\n ", HTML.TD(), "\n "), "\n "), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"layoutChooser.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/layoutChooser/layoutChooser.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _this = this; var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 1); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 2); module.watch(require("meteor/ohif:viewerbase")); var viewportUtils; module.watch(require("../../../lib/viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 3); Template.layoutChooser.onRendered(function () { var instance = Template.instance(); /** * Adds the 'hover' class to cells above and to the left of the current cell * This is used to "fill in" the grid that the user will change the layout to, * if they click on a specific table cell. * * @param currentCell */ instance.highlightCells = function (currentCell) { var cells = _this.$('.layoutChooser table td'); cells.removeClass('hover'); currentCell = _this.$(currentCell); var table = currentCell.parents('.layoutChooser table').get(0); var rowIndex = currentCell.closest('tr').index(); var columnIndex = currentCell.index(); // Loop through the table row by row // and cell by cell to apply the highlighting for (var i = table.rows.length - 1; i >= 0; i--) { var row = table.rows[i]; if (i <= rowIndex) { for (var j = row.cells.length - 1; j >= 0; j--) { if (j <= columnIndex) { var cell = row.cells[j]; cell.classList.add('hover'); } } } } }; // Refresh layout chooser highlighting based on current viewports state instance.refreshHighlights = function () { // Stop here if layoutManager is not defined yet if (!OHIF.viewerbase.layoutManager) { return; } // Get the layout rows and columns amount var info = OHIF.viewerbase.layoutManager.layoutProps; // get the limiter cell var cell = instance.$('tr').eq(info.rows - 1).children().eq(info.columns - 1); // Highlight all cells before the limiter instance.highlightCells(cell); }; instance.autorun(function () { // Run this computation every time the viewer layout is changed Session.get('LayoutManagerUpdated'); instance.refreshHighlights(); }); }); Template.layoutChooser.events({ 'touchstart .layoutChooser table td, mouseenter .layoutChooser table td': function (event, instance) { instance.highlightCells(event.currentTarget); }, 'mouseleave .layoutChooser': function (event, instance) { instance.refreshHighlights(); }, 'click .layoutChooser table td': function (event, instance) { var $currentCell = instance.$(event.currentTarget); var rowIndex = $currentCell.closest('tr').index(); var columnIndex = $currentCell.index(); // Add 1 because the indices start from zero var layoutProps = { rows: rowIndex + 1, columns: columnIndex + 1 }; OHIF.viewerbase.layoutManager.layoutTemplateName = 'gridLayout'; OHIF.viewerbase.layoutManager.layoutProps = layoutProps; OHIF.viewerbase.layoutManager.updateViewports(); var $dropdown = instance.$('.layoutChooser'); viewportUtils.toggleDialog($dropdown); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"cineDialog":{"template.cineDialog.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/cineDialog/template.cineDialog.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("cineDialog"); Template["cineDialog"] = new Template("Template.cineDialog", (function() { var view = this; return HTML.getTag("dialog")({ id: "cineDialog" }, "\n ", Blaze._TemplateWith(function() { return { id: Spacebars.call("cineDialogForm"), class: Spacebars.call(Spacebars.dataMustache(view.lookup("getClassNames"), "dialog-animated noselect")), schema: Spacebars.call(Spacebars.dot(view.lookup("instance"), "schema")), api: Spacebars.call(Spacebars.dot(view.lookup("instance"), "api")) }; }, function() { return Spacebars.include(view.lookupTemplate("form"), function() { return [ "\n ", Blaze._TemplateWith(function() { return { key: Spacebars.call("intervalId") }; }, function() { return Spacebars.include(view.lookupTemplate("inputHidden")); }), "\n ", HTML.DIV({ class: "button-close-container" }, "\n ", HTML.DIV({ class: "button-close" }, HTML.SPAN({ "aria-hidden": "true" }, "x")), "\n "), "\n ", HTML.DIV({ class: "cine-controls" }, "\n ", HTML.DIV({ class: "btn-group" }, "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("btn"), action: Spacebars.call("cineFirst"), title: Spacebars.call("Skip to first image"), disabled: Spacebars.call(Spacebars.dataMustache(view.lookup("buttonDisabled"))) }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return [ "\n ", HTML.I({ class: "fa fa-fast-backward" }), "\n " ]; }); }), "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("btn"), action: Spacebars.call("cinePrevious"), title: Spacebars.call("Previous image"), disabled: Spacebars.call(Spacebars.dataMustache(view.lookup("buttonDisabled"))) }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return [ "\n ", HTML.I({ class: "fa fa-step-backward" }), "\n " ]; }); }), "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call(Spacebars.dataMustache(view.lookup("concat"), "btn ", Spacebars.dataMustache(view.lookup("valueIf"), view.lookup("isPlaying"), "active", ""))), action: Spacebars.call("cineToggle"), title: Spacebars.call("Play / Stop"), disabled: Spacebars.call(Spacebars.dataMustache(view.lookup("buttonDisabled"))) }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return [ "\n ", Blaze.If(function() { return Spacebars.call(view.lookup("isPlaying")); }, function() { return [ "\n ", HTML.I({ class: "fa fa-fw fa-stop" }), "\n " ]; }, function() { return [ "\n ", HTML.I({ class: "fa fa-fw fa-play" }), "\n " ]; }), "\n " ]; }); }), "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("btn"), action: Spacebars.call("cineNext"), title: Spacebars.call("Next image"), disabled: Spacebars.call(Spacebars.dataMustache(view.lookup("buttonDisabled"))) }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return [ "\n ", HTML.I({ class: "fa fa-step-forward" }), "\n " ]; }); }), "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("btn"), action: Spacebars.call("cineLast"), title: Spacebars.call("Skip to last image"), disabled: Spacebars.call(Spacebars.dataMustache(view.lookup("buttonDisabled"))) }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return [ "\n ", HTML.I({ class: "fa fa-fast-forward" }), "\n " ]; }); }), "\n "), "\n "), "\n ", HTML.DIV({ class: "cine-options" }, "\n ", HTML.DIV({ class: "fps-section" }, "\n ", Blaze._TemplateWith(function() { return { key: Spacebars.call("framesPerSecond"), class: Spacebars.call("p-a-0"), labelClass: Spacebars.call("form-group m-a-0"), labelAsDiv: Spacebars.call(true) }; }, function() { return Spacebars.include(view.lookupTemplate("inputRange"), function() { return "\n "; }); }), "\n "), "\n ", HTML.SPAN({ id: "fps" }, Blaze.View("lookup:framerate", function() { return Spacebars.mustache(view.lookup("framerate")); }), " fps"), "\n "), "\n ", HTML.DIV({ class: "cine-navigation" }, "\n ", HTML.DIV({ class: "btn-group" }, "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("btn"), disabled: Spacebars.call(Spacebars.dataMustache(view.lookup("displaySetDisabled"), false)), action: Spacebars.call("displaySetPrevious"), title: Spacebars.call("Previous display set") }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return [ "\n ", HTML.I({ class: "fa fa-toggle-up" }), "\n " ]; }); }), "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("btn"), disabled: Spacebars.call(Spacebars.dataMustache(view.lookup("displaySetDisabled"), true)), action: Spacebars.call("displaySetNext"), title: Spacebars.call("Next display set") }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return [ "\n ", HTML.I({ class: "fa fa-toggle-down" }), "\n " ]; }); }), "\n "), "\n "), "\n " ]; }); }), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"cineDialog.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/cineDialog/cineDialog.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var SimpleSchema; module.watch(require("meteor/aldeed:simple-schema"), { SimpleSchema: function (v) { SimpleSchema = v; } }, 1); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 2); var Tracker; module.watch(require("meteor/tracker"), { Tracker: function (v) { Tracker = v; } }, 3); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 4); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 5); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 6); var cornerstoneTools; module.watch(require("meteor/ohif:cornerstone"), { cornerstoneTools: function (v) { cornerstoneTools = v; } }, 7); var viewportUtils; module.watch(require("../../../lib/viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 8); var switchToImageRelative; module.watch(require("../../../lib/switchToImageRelative"), { switchToImageRelative: function (v) { switchToImageRelative = v; } }, 9); var switchToImageByIndex; module.watch(require("../../../lib/switchToImageByIndex"), { switchToImageByIndex: function (v) { switchToImageByIndex = v; } }, 10); Template.cineDialog.onCreated(function () { var instance = Template.instance(); // Create the data schema for CINE controls instance.schema = new SimpleSchema({ intervalId: { type: Number, optional: true }, loop: { type: Boolean, label: 'Loop', defaultValue: true }, framesPerSecond: { type: Number, label: '', defaultValue: 24, min: 1, max: 90, optional: true } }); // Update the current viewport frame rate instance.updateFramerate = function (rate) { OHIF.viewer.cine.framesPerSecond = rate; // Update playClip toolData for this imageId var element = viewportUtils.getActiveViewportElement(); if (!element) { return; } var playClipData = cornerstoneTools.getToolState(element, 'playClip'); if (!playClipData || !playClipData.data || !playClipData.data.length) { return; } // A valid playClip data object is available. playClipData = playClipData.data[0]; // If the movie is playing, stop/start to update the framerate if (playClipData.intervalId !== void 0) { cornerstoneTools.stopClip(element); cornerstoneTools.playClip(element, OHIF.viewer.cine.framesPerSecond); } else { playClipData.framesPerSecond = OHIF.viewer.cine.framesPerSecond; } Session.set('UpdateCINE', Math.random()); }; // Define the actions API instance.api = { displaySetPrevious: function () { return OHIF.viewerbase.layoutManager.moveDisplaySets(false); }, displaySetNext: function () { return OHIF.viewerbase.layoutManager.moveDisplaySets(true); }, cineToggle: function () { return viewportUtils.toggleCinePlay(); }, cineFirst: function () { return switchToImageByIndex(0); }, cineLast: function () { return switchToImageByIndex(-1); }, cinePrevious: function () { return switchToImageRelative(-1); }, cineNext: function () { return switchToImageRelative(1); }, cineSlowDown: function () { var newValue = OHIF.viewer.cine.framesPerSecond - 1; if (newValue > 0) { instance.updateFramerate(newValue); } }, cineSpeedUp: function () { var newValue = OHIF.viewer.cine.framesPerSecond + 1; if (newValue <= 90) { instance.updateFramerate(newValue); } } }; // Run this computation every time the active viewport is changed instance.autorun(function () { Session.get('activeViewport'); Tracker.afterFlush(function () { // Get the active viewportElement var element = viewportUtils.getActiveViewportElement(); if (!element) { return; } // check if playClip tool has been initialized... var playClipData = cornerstoneTools.getToolState(element, 'playClip'); if (!playClipData) { return; } // Get the cornerstone playClip tool data var toolData = playClipData.data[0]; // Get the cine object var cine = OHIF.viewer.cine; // replace the cine values with the tool data _.extend(cine, toolData); // Set the defaults cine.framesPerSecond = cine.framesPerSecond || 24; cine.loop = _.isUndefined(cine.loop) ? true : cine.loop; // Set the updated data on the form inputs var elementComponent = instance.$('form:first').data('component'); if (elementComponent) { elementComponent.value(cine); } // Update the session to refresh the framerate text Session.set('UpdateCINE', Math.random()); }); }); /** * Set/Reset Window resize handler. This function is a replacement for * ... jQuery's on('resize', func) version which, for some unkown reason * ... is currently not working for this portion of code. * ... Further investigation is necessary. * * This happens because when an event is attached using jQuery's * you can't get it using vanilla JavaScript, it returns null. * You need to use jQuery for that. So, either you use vanilla JS or jQuery * to get an element's event handler. See viewerMain for more details. */ instance.setResizeHandler = function (handler) { if (typeof handler === 'function') { var origHandler = window.onresize; instance.origWindowResizeHandler = typeof origHandler === 'function' ? origHandler : null; window.onresize = function (event) { if (typeof origHandler === 'function') { origHandler.call(window, event); } handler.call(window, event); }; } else { window.onresize = instance.origWindowResizeHandler || null; window.origWindowResizeHandler = null; } }; /** * Set optimal position for Cine dialog. */ instance.setOptimalPosition = function (event, options) { var $viewer = $('#viewer'); var $toolbarElement = $('.toolbarSection .toolbarSectionTools:first'); var $cineDialog = $('#cineDialog'); $cineDialog.width($('#cineDialogForm').outerWidth()); if ($toolbarElement.length < 1 || $cineDialog.length < 1) { return; } if ($cineDialog.data('wasDragged') || $cineDialog.data('wasBounded')) { // restore original handler... instance.setResizeHandler(null); return; } var cineDialogSize = { width: $cineDialog.outerWidth() || 0, height: $cineDialog.outerHeight() || 0 }; var topLeftCoords = { top: 0, left: 0 }; var toolbarRect = { offset: $toolbarElement.offset() || topLeftCoords, width: $toolbarElement.outerWidth() || 0, height: $toolbarElement.outerHeight() || 0 }; var cineDialogCoords = { left: toolbarRect.offset.left + toolbarRect.width + 20, top: toolbarRect.offset.top + toolbarRect.height - cineDialogSize.height }; if (options) { if (options.left) { cineDialogCoords.left = options.left; } if (options.top) { cineDialogCoords.top = options.top; } } // Check if it is out of screen if (cineDialogCoords.top < 0) { cineDialogCoords.top = 0; } else if (cineDialogCoords.top + cineDialogSize.height > $viewer.height()) { cineDialogCoords.top -= cineDialogCoords.top + cineDialogSize.height - $viewer.height(); } if (cineDialogCoords.left < 0) { cineDialogCoords.left = 0; } else if (cineDialogCoords.left + cineDialogSize.width > $viewer.width()) { cineDialogCoords.left -= cineDialogCoords.left + cineDialogSize.width - $viewer.width(); } $cineDialog.css(cineDialogCoords); }; }); Template.cineDialog.onRendered(function () { var instance = Template.instance(); var $dialog = instance.$('#cineDialog'); var singleRowLayout = OHIF.uiSettings.displayEchoUltrasoundWorkflow; // set dialog in optimal position and make sure it continues in a optimal position... // ... when the window has been resized instance.setOptimalPosition(null, { top: singleRowLayout ? 47 : 26 }); // The jQuery method does not seem to be working... // ... $(window).resize(instance.setOptimalPosition) // This requires additional investigation. instance.setResizeHandler(instance.setOptimalPosition); // Make the CINE dialog bounded and draggable $dialog.draggable({ defaultElementCursor: 'move' }).bounded(); // Polyfill for older browsers window.dialogPolyfill.registerDialog($dialog.get(0)); // Prevent dialog from being dragged when user clicks any button var $controls = $dialog.find('.cine-navigation, .cine-controls, .cine-options'); $controls.on('mousedown touchstart', function (event) { return event.stopPropagation(); }); }); Template.cineDialog.onDestroyed(function () { var instance = Template.instance(); // remove resize handler... instance.setResizeHandler(null); }); Template.cineDialog.events({ 'change [data-key=loop] input': function (event, instance) { var element = viewportUtils.getActiveViewportElement(); OHIF.viewer.cine.loop = $(event.currentTarget).is(':checked'); // Update playClip tool data if available. var playClipData = cornerstoneTools.getToolState(element, 'playClip'); if (playClipData && playClipData.data && playClipData.data.length > 0) { playClipData.data[0].loop = OHIF.viewer.cine.loop; } }, 'input [data-key=framesPerSecond] input, change [data-key=framesPerSecond] input': function (event, instance) { // Update the FPS text onscreen var rate = parseFloat($(event.currentTarget).val()); instance.updateFramerate(rate); }, 'click .button-close': function (event, instance) { OHIF.commands.run('toggleCineDialog'); } }); Template.cineDialog.helpers({ isPlaying: function () { return viewportUtils.isPlaying(); }, framerate: function () { Session.get('UpdateCINE'); return OHIF.viewer.cine.framesPerSecond.toFixed(1); }, displaySetDisabled: function (isNext) { Session.get('LayoutManagerUpdated'); // @TODO: Investigate why this is running while OHIF.viewerbase.layoutManager is undefined if (!OHIF.viewerbase.layoutManager) { return; } return !OHIF.viewerbase.layoutManager.canMoveDisplaySets(isNext) ? 'disabled' : ''; }, buttonDisabled: function () { return viewportUtils.hasMultipleFrames(); }, getClassNames: function (baseClass) { var style = OHIF.uiSettings.displayEchoUltrasoundWorkflow ? 'single' : 'double'; return baseClass + " " + style + "-row-style"; } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"downloadDialog":{"template.downloadDialog.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/downloadDialog/template.downloadDialog.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("imageDownloadDialog"); Template["imageDownloadDialog"] = new Template("Template.imageDownloadDialog", (function() { var view = this; return Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("extend"), view.lookup("."), Spacebars.kw({ title: "Download High Quality Image", class: "themed", dialogClass: "modal-lg", formClass: "form-themed", confirmLabel: "Download Image", confirmCallback: Spacebars.dot(view.lookup("instance"), "getConfirmCallback"), cancelLabel: "Cancel", id: "imageDownloadDialog", schema: Spacebars.dot(view.lookup("instance"), "schema") })); }, function() { return Spacebars.include(view.lookupTemplate("dialogForm"), function() { return [ "\n ", HTML.H5("Please specify the dimensions, filename, and desired type for the output image."), "\n ", HTML.DIV({ class: "card-round" }, "\n ", HTML.DIV({ class: "row m-t-2" }, "\n ", HTML.DIV({ class: "col-lg-4" }, "\n ", HTML.TABLE({ class: "full-width" }, "\n ", HTML.TBODY("\n ", HTML.TR("\n ", HTML.TD({ class: "text-right p-r-1 nowrap" }, "Image width (px)"), "\n ", HTML.TD(Blaze._TemplateWith(function() { return { key: Spacebars.call("width"), min: Spacebars.call("1"), max: Spacebars.call("16384") }; }, function() { return Spacebars.include(view.lookupTemplate("inputNumber")); })), "\n ", HTML.TD({ class: "p-l-1", rowspan: "2" }, "\n ", HTML.BUTTON({ class: function() { return [ "btn btn-secondary js-keep-aspect ", Blaze.If(function() { return Spacebars.call(view.lookup("keepAspect")); }, function() { return "active"; }) ]; }, title: "Keep aspect ratio" }, "\n ", HTML.I({ class: function() { return [ "fa fa-chain", Blaze.Unless(function() { return Spacebars.call(view.lookup("keepAspect")); }, function() { return "-broken"; }) ]; } }), "\n "), "\n "), "\n "), "\n ", HTML.TR("\n ", HTML.TD({ class: "text-right p-r-1 nowrap" }, "Image height (px)"), "\n ", HTML.TD(Blaze._TemplateWith(function() { return { key: Spacebars.call("height"), min: Spacebars.call("1"), max: Spacebars.call("16384") }; }, function() { return Spacebars.include(view.lookupTemplate("inputNumber")); })), "\n "), "\n "), "\n "), "\n "), "\n ", HTML.DIV({ class: "col-lg-5" }, "\n ", HTML.TABLE({ class: "full-width" }, "\n ", HTML.TBODY("\n ", HTML.TR("\n ", HTML.TD({ class: "text-right p-r-1" }, "File name"), "\n ", HTML.TD(Blaze._TemplateWith(function() { return { key: Spacebars.call("name") }; }, function() { return Spacebars.include(view.lookupTemplate("inputText")); })), "\n "), "\n ", HTML.TR("\n ", HTML.TD({ class: "text-right p-r-1" }, "File type"), "\n ", HTML.TD(Blaze._TemplateWith(function() { return { key: Spacebars.call("type"), hideSearch: Spacebars.call(true) }; }, function() { return Spacebars.include(view.lookupTemplate("inputSelect")); })), "\n "), "\n "), "\n "), "\n "), "\n ", HTML.DIV({ class: "col-lg-3" }, "\n ", HTML.TABLE({ class: "full-width" }, "\n ", HTML.TBODY("\n ", HTML.TR("\n ", HTML.TD({ class: "text-right", colspan: "2" }, Blaze._TemplateWith(function() { return { key: Spacebars.call("showAnnotations") }; }, function() { return Spacebars.include(view.lookupTemplate("inputCheckbox")); })), "\n "), "\n "), "\n "), "\n "), "\n "), "\n "), "\n ", HTML.DIV({ class: "viewport-element hidden" }), "\n ", HTML.DIV({ class: "image-preview card-round m-t-2 text-center" }, "\n ", HTML.H4({ class: "m-t-0" }, "Image Preview"), "\n ", HTML.IMG({ class: "viewport-preview" }), "\n "), "\n " ]; }); }); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"downloadDialog.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/downloadDialog/downloadDialog.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var Tracker; module.watch(require("meteor/tracker"), { Tracker: function (v) { Tracker = v; } }, 1); var ReactiveVar; module.watch(require("meteor/reactive-var"), { ReactiveVar: function (v) { ReactiveVar = v; } }, 2); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 3); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 4); var SimpleSchema; module.watch(require("meteor/aldeed:simple-schema"), { SimpleSchema: function (v) { SimpleSchema = v; } }, 5); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 6); var cornerstone, cornerstoneTools; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; }, cornerstoneTools: function (v) { cornerstoneTools = v; } }, 7); OHIF.viewerbase.getImageDownloadDialogAnnotationTools = function () { return ['length', 'probe', 'simpleAngle', 'arrowAnnotate', 'ellipticalRoi', 'rectangleRoi']; }; Template.imageDownloadDialog.onCreated(function () { var instance = Template.instance(); instance.schema = new SimpleSchema({ width: { type: Number }, height: { type: Number }, name: { type: String, defaultValue: 'image' }, type: { type: String, allowedValues: ['jpeg', 'png'], valuesLabels: ['JPEG', 'PNG'], defaultValue: 'jpeg' }, showAnnotations: { type: Boolean, label: 'Show Annotations', defaultValue: true } }); instance.changeObserver = new Tracker.Dependency(); instance.keepAspect = new ReactiveVar(true); instance.showAnnotations = new ReactiveVar(false); instance.lastImage = {}; instance.getConfirmCallback = function () { return function () { instance.downloadImage(); }; }; }); Template.imageDownloadDialog.onRendered(function () { var instance = Template.instance(); var viewportUtils = OHIF.viewerbase.viewportUtils; instance.$viewportElement = instance.$('.viewport-element'); instance.viewportElement = instance.$viewportElement[0]; instance.$viewportPreview = instance.$('.viewport-preview'); instance.viewportPreview = instance.$viewportPreview[0]; cornerstone.enable(instance.viewportElement); instance.downloadCanvas = $(instance.viewportElement).find('canvas')[0]; instance.form = instance.$('form').data('component'); instance.setElementSize = function (element, canvas, size, value) { $(element)[size](value); canvas[size] = value; canvas.style[size] = value + "px"; instance.form.item(size).$element.val(value); }; instance.toggleAnnotations = function (toggle) { var action = toggle ? 'enable' : 'disable'; var annotationTools = OHIF.viewerbase.getImageDownloadDialogAnnotationTools(); annotationTools.forEach(function (tool) { return cornerstoneTools[tool][action](instance.viewportElement); }); }; instance.updateViewportPreview = function () { instance.$viewportElement.one('cornerstoneimagerendered', function (event) { // Wait for the tools to handle CornerstoneImageRendered event Tracker.afterFlush(function () { var enabledElement = cornerstone.getEnabledElement(event.currentTarget); var formData = instance.form.value(); var image = instance.viewportPreview; var type = 'image/' + formData.type; var dataUrl = instance.downloadCanvas.toDataURL(type, 1); image.src = dataUrl; var $element = $(enabledElement.element); var width = $element.width(); var height = $element.height(); if (width > 512 || height > 512) { var multiplier = 512 / Math.max(width, height); height *= multiplier; width *= multiplier; } image.width = width; image.height = height; }); }); }; instance.downloadImage = function () { var formData = instance.form.value(); var filename = formData.name + "." + formData.type; var mimetype = "image/" + formData.type; cornerstoneTools.saveAs(instance.viewportElement, filename, mimetype); }; instance.autorun(function () { instance.changeObserver.depend(); Session.get('UpdateDownloadViewport'); var activeViewport = viewportUtils.getActiveViewportElement(); if (activeViewport) { var enabledElement = cornerstone.getEnabledElement(activeViewport); var viewport = Object.assign({}, enabledElement.viewport); delete viewport.scale; viewport.translation = { x: 0, y: 0 }; cornerstone.loadImage(enabledElement.image.imageId).then(function (image) { instance.lastImage = image; var viewportElement = instance.viewportElement, downloadCanvas = instance.downloadCanvas; var formData = instance.form.value(); cornerstone.displayImage(viewportElement, image); cornerstone.setViewport(viewportElement, viewport); cornerstone.resize(viewportElement, true); instance.toggleAnnotations(formData.showAnnotations); var width = Math.min(formData.width || image.width, 16384); var height = Math.min(formData.height || image.height, 16384); instance.setElementSize(viewportElement, downloadCanvas, 'width', width); instance.setElementSize(viewportElement, downloadCanvas, 'height', height); cornerstone.fitToWindow(viewportElement); instance.updateViewportPreview(); }); } }); }); Template.imageDownloadDialog.onDestroyed(function () { var instance = Template.instance(); cornerstone.disable(instance.viewportElement); }); Template.imageDownloadDialog.events({ 'click .js-keep-aspect': function (event, instance) { var currentState = instance.keepAspect.get(); instance.keepAspect.set(!currentState); instance.$('[data-key=width]').trigger('input'); }, 'change [data-key=showAnnotations], change [data-key=type]': function (event, instance) { instance.changeObserver.changed(); }, 'input [data-key=width]': function (event, instance) { var viewportElement = instance.viewportElement, downloadCanvas = instance.downloadCanvas; var formData = instance.form.value(); var _instance$lastImage = instance.lastImage, width = _instance$lastImage.width, height = _instance$lastImage.height; var newWidth = formData.width; instance.setElementSize(viewportElement, downloadCanvas, 'width', newWidth); if (instance.keepAspect.get()) { var multiplier = newWidth / width; var newHeight = Math.round(height * multiplier); instance.setElementSize(viewportElement, downloadCanvas, 'height', newHeight); } instance.changeObserver.changed(); }, 'input [data-key=height]': function (event, instance) { var viewportElement = instance.viewportElement, downloadCanvas = instance.downloadCanvas; var formData = instance.form.value(); var _instance$lastImage2 = instance.lastImage, width = _instance$lastImage2.width, height = _instance$lastImage2.height; var newHeight = formData.height; instance.setElementSize(viewportElement, downloadCanvas, 'height', newHeight); if (instance.keepAspect.get()) { var multiplier = newHeight / height; var newWidth = Math.round(width * multiplier); instance.setElementSize(viewportElement, downloadCanvas, 'width', newWidth); } instance.changeObserver.changed(); } }); Template.imageDownloadDialog.helpers({ keepAspect: function () { return Template.instance().keepAspect.get(); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"toolbarSectionButton":{"template.toolbarSectionButton.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/toolbarSectionButton/template.toolbarSectionButton.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("toolbarSectionButton"); Template["toolbarSectionButton"] = new Template("Template.toolbarSectionButton", (function() { var view = this; return Blaze.If(function() { return Spacebars.call(Spacebars.dot(view.lookup("."), "buttonTemplateName")); }, function() { return [ "\n ", Blaze._TemplateWith(function() { return { template: Spacebars.call(Spacebars.dot(view.lookup("."), "buttonTemplateName")), data: Spacebars.call(view.lookup(".")) }; }, function() { return Spacebars.include(function() { return Spacebars.call(Template.__dynamic); }); }), "\n " ]; }, function() { return [ "\n ", HTML.DIV({ id: function() { return Spacebars.mustache(Spacebars.dot(view.lookup("."), "id")); }, tabindex: "1", class: function() { return [ "toolbarSectionButton rp-x-1 ", Spacebars.mustache(Spacebars.dot(view.lookup("."), "classes")), " ", Spacebars.mustache(view.lookup("activeClass")), " ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("or"), Spacebars.dot(view.lookup("."), "disabled"), Spacebars.dataMustache(view.lookup("disableButton"))); }, function() { return "disabled"; }), " ", Blaze.If(function() { return Spacebars.call(view.lookup("hasSubTools")); }, function() { return "expandable"; }) ]; }, title: function() { return Spacebars.mustache(Spacebars.dot(view.lookup("."), "tooltipTitle")); } }, "\n ", HTML.DIV({ class: "svgContainer" }, "\n ", Blaze.Let({ svg: function() { return Spacebars.call(view.lookup("svgLink")); }, icon: function() { return Spacebars.call(view.lookup("iconClasses")); } }, function() { return [ "\n ", Blaze.If(function() { return Spacebars.call(view.lookup("svg")); }, function() { return [ "\n ", HTML.SVG("\n ", HTML.USE({ "xlink:href": function() { return Spacebars.mustache(view.lookup("absoluteUrl"), view.lookup("svg")); } }), "\n "), "\n " ]; }, function() { return [ "\n ", HTML.I({ class: function() { return Spacebars.mustache(view.lookup("icon")); } }), "\n " ]; }), "\n " ]; }), "\n "), "\n ", HTML.DIV({ class: "buttonLabel" }, "\n ", HTML.SPAN(Blaze.View("lookup:..title", function() { return Spacebars.mustache(Spacebars.dot(view.lookup("."), "title")); })), "\n ", Blaze.If(function() { return Spacebars.call(view.lookup("hasSubTools")); }, function() { return [ "\n ", HTML.I({ class: "fa fa-caret-down expanded-status", "aria-hidden": "true" }), "\n " ]; }), "\n "), "\n ", Blaze.If(function() { return Spacebars.call(view.lookup("hasSubTools")); }, function() { return [ "\n ", HTML.DIV({ class: "toolbarSectionDrawerContainer" }, "\n ", HTML.DIV({ class: "toolbarSectionDrawer" }, "\n ", Blaze.If(function() { return Spacebars.call(Spacebars.dot(view.lookup("."), "subToolsTemplateName")); }, function() { return [ "\n ", Blaze._TemplateWith(function() { return { template: Spacebars.call(Spacebars.dot(view.lookup("."), "subToolsTemplateName")), data: Spacebars.call(view.lookup(".")) }; }, function() { return Spacebars.include(function() { return Spacebars.call(Template.__dynamic); }); }), "\n " ]; }, function() { return [ "\n ", Blaze.If(function() { return Spacebars.call(Spacebars.dot(view.lookup("."), "subTools")); }, function() { return [ "\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(Spacebars.dot(view.lookup("."), "subTools")), _variable: "subTool" }; }, function() { return [ "\n ", Blaze._TemplateWith(function() { return Spacebars.call(view.lookup("subTool")); }, function() { return Spacebars.include(view.lookupTemplate("toolbarSectionButton")); }), "\n " ]; }), "\n " ]; }), "\n " ]; }), "\n "), "\n "), " \n " ]; }), "\n "), "\n " ]; }); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"toolbarSectionButton.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/toolbarSectionButton/toolbarSectionButton.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 1); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 2); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 3); Template.toolbarSectionButton.onCreated(function () { var instance = Template.instance(); instance.isActive = function (activeToolId) { OHIF.commands.last.dep.depend(); var subTools = instance.data.subTools; var currentId = instance.data.id; var isCurrentTool = currentId === activeToolId; var isSubTool = subTools && _.findWhere(subTools, { id: activeToolId }); var activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || []; var isActiveCommandButton = activeCommandButtons.indexOf(instance.data.id) !== -1; var isActive = typeof instance.data.active === 'function' && instance.data.active(); // Check if the current tool, a sub tool or a command button is active return isActive || isCurrentTool || isSubTool || isActiveCommandButton; }; instance.getActiveToolSubProperty = function (propertyName, activeToolId) { var instance = Template.instance(); var subTools = instance.data.subTools; var defaultProperty = instance.data[propertyName]; var currentId = instance.data.id; if (subTools && activeToolId !== currentId && instance.isActive(activeToolId)) { var subTool = _.findWhere(subTools, { id: activeToolId }); return subTool ? subTool[propertyName] : defaultProperty; } else { return defaultProperty; } }; instance.autorun(function (computation) { Session.get('ToolManagerActiveToolUpdated'); // Get the last executed command var lastCommand = OHIF.commands.last.get(); // Prevent running this computation on its first run if (computation.firstRun) return; // Stop here if it's not the last command or if it's already an active tool var id = instance.data.id; var activeToolId = OHIF.viewerbase.toolManager.getActiveTool(); if (lastCommand !== id || instance.isActive(activeToolId)) return; // Add an active class to a button for 100ms to give the impression the button was pressed var flashButton = function ($element) { $element.addClass('active'); setTimeout(function () { if ($element.hasClass('expandable') && $element.find('.toolbarSectionButton.active').length) return; var activeToolId = OHIF.viewerbase.toolManager.getActiveTool(); var isActive = instance.isActive(activeToolId); if (!isActive) { $element.removeClass('active'); } }, 100); }; // Flash the active button var $button = instance.$('.toolbarSectionButton').first(); flashButton($button); // Flash the parent button as well in case of this button is inside a drawer var $parentButton = $button.closest('.toolbarSectionButton.expandable'); if ($parentButton.length) { flashButton($parentButton); } }); }); Template.toolbarSectionButton.helpers({ activeClass: function () { Session.get('ToolManagerActiveToolUpdated'); var instance = Template.instance(); var activeToolId = OHIF.viewerbase.toolManager.getActiveTool(); var isActive = instance.isActive(activeToolId); return isActive ? 'active' : ''; }, svgLink: function () { Session.get('ToolManagerActiveToolUpdated'); var instance = Template.instance(); var activeToolId = OHIF.viewerbase.toolManager.getActiveTool(); var svgLink = instance.getActiveToolSubProperty('svgLink', activeToolId); return _.isFunction(svgLink) ? svgLink() : svgLink; }, iconClasses: function () { Session.get('ToolManagerActiveToolUpdated'); var instance = Template.instance(); var activeToolId = OHIF.viewerbase.toolManager.getActiveTool(); var iconClasses = instance.getActiveToolSubProperty('iconClasses', activeToolId); return _.isFunction(iconClasses) ? iconClasses() : iconClasses; }, disableButton: function () { Session.get('activeViewport'); Session.get('LayoutManagerUpdated'); var instance = Template.instance(); var isCommandDisabled = OHIF.commands.isDisabled(instance.data.id); var isFunctionDisabled = instance.data.disableFunction && instance.data.disableFunction(); return isCommandDisabled || isFunctionDisabled; }, hasSubTools: function () { return this.subTools || this.subToolsTemplateName; } }); Template.toolbarSectionButton.events({ 'click .toolbarSectionButton:not(.expandable)': function (event, instance) { // Prevent the event from bubbling to parent tools event.stopPropagation(); var $currentTarget = $(event.currentTarget); // Stop here if the button is disabled or customAction if ($currentTarget.hasClass('disabled') || $currentTarget.hasClass('customAction')) { return; } // Run the command attached to the button OHIF.commands.run(instance.data.id); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"toolbarSectionTools":{"template.toolbarSectionTools.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/toolbarSectionTools/template.toolbarSectionTools.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("toolbarSectionTools"); Template["toolbarSectionTools"] = new Template("Template.toolbarSectionTools", (function() { var view = this; return HTML.DIV({ class: "toolbarSectionTools pull-left m-t-1 rm-l-3" }, "\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(view.lookup("toolbarButtons")), _variable: "toolbarButton" }; }, function() { return [ "\n ", Blaze._TemplateWith(function() { return Spacebars.call(view.lookup("toolbarButton")); }, function() { return Spacebars.include(view.lookupTemplate("toolbarSectionButton")); }), "\n " ]; }), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"toolbarSectionTools.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/toolbarSectionTools/toolbarSectionTools.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 1); Template.toolbarSectionTools.events({ 'click .expandable': function (event, instance) { var $target = $(event.currentTarget); var isExpanded = $target.hasClass('expanded'); $target.toggleClass('expanded', !isExpanded); // Remove the previously set repositioning css attribute var $box = $target.find('.toolbarSectionDrawerContainer:first'); $box.css('left', ''); // Stop here if the tool group is not expanded if (isExpanded) { return; } // Move the box left or right if it is overflowing the window var transitionendHandler = function (event) { var originalEvent = event.originalEvent; var propertyName = originalEvent && originalEvent.propertyName; if (propertyName && propertyName === 'transform') { $target.off('transitionend', transitionendHandler); } else { return; } var boxWidth = $box.outerWidth(); var start = $box.offset().left; var bodyWidth = $(document.body).outerWidth(); var end = start + boxWidth; if (start < 0) { $box.css('left', "calc(50% - " + start + "px)"); } else if (end > bodyWidth) { var diff = end - bodyWidth; $box.css('left', "calc(50% - " + diff + "px)"); } }; // Attach the handler to deal with position fixing $target.on('transitionend', transitionendHandler); }, 'focusout .expandable': function (event, instance) { var target = event.target; var currentTarget = event.currentTarget; // Postpone the execution to be able to get the focused element Meteor.defer(function () { var $focused = $(':focus'); var $expandable = $(currentTarget).closest('.expandable'); var focusInside = $expandable.find(':focus').length; // Check if the expandable lost the focus if (!$focused.length || !focusInside) { // Stop here if focus is going from subtool to expandable tool if (currentTarget !== target && $focused[0] === currentTarget) { return; } $expandable.removeClass('expanded'); } }); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"userPreferences":{"template.dialog.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/userPreferences/template.dialog.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("userPreferencesDialog"); Template["userPreferencesDialog"] = new Template("Template.userPreferencesDialog", (function() { var view = this; return Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("extend"), view.lookup("."), Spacebars.kw({ class: "themed", dialogClass: "dialog-user-preferences modal-lg", title: "User Preferences" })); }, function() { return Spacebars.include(view.lookupTemplate("dialogSimple"), function() { return [ "\n ", HTML.DIV({ class: "dialog-separator-after" }, "\n ", HTML.UL({ class: "nav nav-tabs" }, "\n ", HTML.LI({ role: "presentation", class: function() { return Spacebars.mustache(view.lookup("tabClasses"), "hotkeys"); } }, "\n ", HTML.A({ href: "#", "data-id": "hotkeys" }, "Keyboard Shortcuts"), "\n "), "\n ", HTML.LI({ role: "presentation", class: function() { return Spacebars.mustache(view.lookup("tabClasses"), "wwwc"); } }, "\n ", HTML.A({ href: "#", "data-id": "wwwc" }, "Window/Levels"), "\n "), "\n "), "\n "), "\n ", HTML.DIV({ class: function() { return Blaze.Unless(function() { return Spacebars.dataMustache(view.lookup("eq"), Spacebars.dot(view.lookup("instance"), "activeTab", "get"), "hotkeys"); }, function() { return "hidden"; }); } }, "\n ", Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("extend"), Spacebars.kw({ contextName: "viewer" })); }, function() { return Spacebars.include(view.lookupTemplate("hotkeysForm")); }), "\n "), "\n ", HTML.DIV({ class: function() { return Blaze.Unless(function() { return Spacebars.dataMustache(view.lookup("eq"), Spacebars.dot(view.lookup("instance"), "activeTab", "get"), "wwwc"); }, function() { return "hidden"; }); } }, "\n ", Spacebars.include(view.lookupTemplate("windowLevelPresetsForm")), "\n "), "\n " ]; }); }); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"dialog.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/userPreferences/dialog.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var ReactiveVar; module.watch(require("meteor/reactive-var"), { ReactiveVar: function (v) { ReactiveVar = v; } }, 1); Template.userPreferencesDialog.onCreated(function () { var instance = Template.instance(); instance.activeTab = new ReactiveVar('hotkeys'); }); Template.userPreferencesDialog.events({ 'click .nav-tabs li a': function (event, instance) { var tabId = $(event.currentTarget).attr('data-id'); instance.activeTab.set(tabId); } }); Template.userPreferencesDialog.helpers({ tabClasses: function (tabId) { var instance = Template.instance(); var activeTab = instance.activeTab.get(); return tabId === activeTab ? 'active' : ''; } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"confirmDeleteDialog":{"template.confirmDeleteDialog.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/confirmDeleteDialog/template.confirmDeleteDialog.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("confirmDeleteDialog"); Template["confirmDeleteDialog"] = new Template("Template.confirmDeleteDialog", (function() { var view = this; return HTML.DIV({ id: "confirmDeleteDialog", class: "dialog-animated", tabindex: "0" }, "\n ", Blaze.If(function() { return Spacebars.call(view.lookup("title")); }, function() { return [ "\n ", HTML.H5(Blaze.View("lookup:title", function() { return Spacebars.mustache(view.lookup("title")); })), "\n " ]; }, function() { return [ "\n ", HTML.H5("Remove data from Timepoint?"), "\n " ]; }), "\n ", Blaze.If(function() { return Spacebars.call(view.lookup("text")); }, function() { return [ "\n ", HTML.P(Blaze.View("lookup:text", function() { return Spacebars.mustache(view.lookup("text")); })), "\n " ]; }, function() { return [ "\n ", HTML.P("Are you sure you would like to remove the measurement data at this timepoint?"), "\n " ]; }), HTML.Raw('\n \n \n ')); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"confirmDeleteDialog.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/confirmDeleteDialog/confirmDeleteDialog.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var dialogUtils; module.watch(require("../../../lib/dialogUtils"), { dialogUtils: function (v) { dialogUtils = v; } }, 1); // Global object of key names (TODO: put this somewhere else) var keys = { ESC: 27, ENTER: 13 }; Template.confirmDeleteDialog.events({ 'click #cancel, click #close': function () { // Action canceled, just close dialog without calling callback dialogUtils.closeHandler(false); }, 'click #confirm': function () { // Action confirmed, close dialog and calls callback, if exists dialogUtils.closeHandler(); }, 'keydown #confirmDeleteDialog': function (e) { // Action canceled, just close dialog without calling callback if (e.which === keys.ESC) { dialogUtils.closeHandler(false); return false; } if (this.keyPressAllowed === false) { return; } // If Enter is pressed if (e.which === keys.ENTER) { // Action confirmed, close dialog and calls callback, if exists dialogUtils.closeHandler(); } } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"textMarkerDialogs":{"template.textMarkerDialogs.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/textMarkerDialogs/template.textMarkerDialogs.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("textMarkerDialogs"); Template["textMarkerDialogs"] = new Template("Template.textMarkerDialogs", (function() { var view = this; return [ HTML.getTag("dialog")({ id: "textMarkerOptionsDialog", oncontextmenu: "return false", class: "textMarkerDialog noselect" }, "\n ", HTML.H5("Spine Labels"), "\n ", HTML.A({ class: "closeTextMarkerDialogs" }, Spacebars.include(view.lookupTemplate("iconCrossCircle"))), "\n ", HTML.DIV({ class: "optionsDiv" }, "\n ", HTML.DIV({ class: "select2-wrapper optionBox" }, "\n ", HTML.LABEL({ for: "startFrom" }, "Label: "), "\n ", HTML.SELECT({ name: "start", id: "startFrom", tabindex: "-1", class: "select2" }, "\n ", HTML.Comment(" Cervical spine !"), "\n ", HTML.OPTION({ value: "C1", selected: "" }, "C1"), "\n ", HTML.OPTION({ value: "C2" }, "C2"), "\n ", HTML.OPTION({ value: "C3" }, "C3"), "\n ", HTML.OPTION({ value: "C4" }, "C4"), "\n ", HTML.OPTION({ value: "C5" }, "C5"), "\n ", HTML.OPTION({ value: "C6" }, "C6"), "\n ", HTML.OPTION({ value: "C7" }, "C7"), "\n\n ", HTML.Comment(" Thoracic spine !"), "\n ", HTML.OPTION({ value: "T1" }, "T1"), "\n ", HTML.OPTION({ value: "T2" }, "T2"), "\n ", HTML.OPTION({ value: "T3" }, "T3"), "\n ", HTML.OPTION({ value: "T4" }, "T4"), "\n ", HTML.OPTION({ value: "T5" }, "T5"), "\n ", HTML.OPTION({ value: "T6" }, "T6"), "\n ", HTML.OPTION({ value: "T7" }, "T7"), "\n ", HTML.OPTION({ value: "T8" }, "T8"), "\n ", HTML.OPTION({ value: "T9" }, "T9"), "\n ", HTML.OPTION({ value: "T10" }, "T10"), "\n ", HTML.OPTION({ value: "T11" }, "T11"), "\n ", HTML.OPTION({ value: "T12" }, "T12"), "\n\n ", HTML.Comment(" Lumbar spine !"), "\n ", HTML.OPTION({ value: "L1" }, "L1"), "\n ", HTML.OPTION({ value: "L2" }, "L2"), "\n ", HTML.OPTION({ value: "L3" }, "L3"), "\n ", HTML.OPTION({ value: "L4" }, "L4"), "\n ", HTML.OPTION({ value: "L5" }, "L5"), "\n "), "\n "), "\n ", HTML.DIV({ class: "optionBox" }, "\n ", HTML.DIV({ class: "btn-group iconSwitch", "data-toggle": "buttons" }, "\n ", HTML.LABEL({ for: "ascending", class: "btn btn-link", title: "Add labels from head to feet (down) or feet to head (up)", "data-toggle": "tooltip", "data-container": "body" }, "\n ", HTML.INPUT({ type: "checkbox", id: "ascending" }), " ", HTML.SPAN({ class: "on" }, HTML.I({ class: "fa fa-long-arrow-up", "aria-hidden": "true" })), " ", HTML.SPAN({ class: "off" }, HTML.I({ class: "fa fa-long-arrow-down", "aria-hidden": "true" })), "\n "), "\n "), "\n "), "\n ", HTML.BUTTON({ id: "clearLabels", class: "btn viewerBtn btn-xs", type: "button" }, "\n Clear Labels ", HTML.I({ class: "viewerIcon-clear" }), "\n "), "\n "), " \n "), "\n\n ", HTML.getTag("dialog")({ id: "textMarkerRelabelDialog", oncontextmenu: "return false", class: "textMarkerDialog noselect" }, "\n ", HTML.H5("Change Spine Label"), "\n ", HTML.DIV({ class: "relabelOptions" }, "\n\n ", HTML.DIV({ class: "select2-wrapper optionBox" }, "\n ", HTML.LABEL({ for: "relabelSelect" }, "Label:"), "\n ", HTML.SELECT({ name: "relabelSelect", class: "relabelSelect" }, "\n ", HTML.Comment(" Cervical spine !"), "\n ", HTML.OPTION({ value: "C1" }, "C1"), "\n ", HTML.OPTION({ value: "C2" }, "C2"), "\n ", HTML.OPTION({ value: "C3" }, "C3"), "\n ", HTML.OPTION({ value: "C4" }, "C4"), "\n ", HTML.OPTION({ value: "C5" }, "C5"), "\n ", HTML.OPTION({ value: "C6" }, "C6"), "\n ", HTML.OPTION({ value: "C7" }, "C7"), "\n\n ", HTML.Comment(" Thoracic spine !"), "\n ", HTML.OPTION({ value: "T1" }, "T1"), "\n ", HTML.OPTION({ value: "T2" }, "T2"), "\n ", HTML.OPTION({ value: "T3" }, "T3"), "\n ", HTML.OPTION({ value: "T4" }, "T4"), "\n ", HTML.OPTION({ value: "T5" }, "T5"), "\n ", HTML.OPTION({ value: "T6" }, "T6"), "\n ", HTML.OPTION({ value: "T7" }, "T7"), "\n ", HTML.OPTION({ value: "T8" }, "T8"), "\n ", HTML.OPTION({ value: "T9" }, "T9"), "\n ", HTML.OPTION({ value: "T10" }, "T10"), "\n ", HTML.OPTION({ value: "T11" }, "T11"), "\n ", HTML.OPTION({ value: "T12" }, "T12"), "\n\n ", HTML.Comment(" Lumbar spine !"), "\n ", HTML.OPTION({ value: "L1" }, "L1"), "\n ", HTML.OPTION({ value: "L2" }, "L2"), "\n ", HTML.OPTION({ value: "L3" }, "L3"), "\n ", HTML.OPTION({ value: "L4" }, "L4"), "\n ", HTML.OPTION({ value: "L5" }, "L5"), "\n "), "\n "), "\n "), "\n ", HTML.DIV({ class: "relabelButtons" }, "\n ", HTML.BUTTON({ class: "relabelRemove btn btn-xs btn-secondary viewerBtn" }, "Delete"), "\n ", HTML.BUTTON({ class: "relabelConfirm btn btn-xs viewerBtn" }, "Save"), "\n "), "\n ", HTML.DIV({ class: "dialog arrow" }, "\n "), "\n ") ]; })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"textMarkerDialogs.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/textMarkerDialogs/textMarkerDialogs.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 1); var toolManager; module.watch(require("../../../lib/toolManager"), { toolManager: function (v) { toolManager = v; } }, 2); var viewportUtils; module.watch(require("../../../lib/viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 3); Template.textMarkerDialogs.events({ 'change #startFrom': function (e) { var config = cornerstoneTools.textMarker.getConfiguration(); config.current = $(e.target).val(); //console.log("Changed starting point to: " + config.current); }, 'change #ascending': function (e) { var config = cornerstoneTools.textMarker.getConfiguration(); config.ascending = $(e.target).is(':checked'); var currentIndex = config.markers.indexOf(config.current); config.current = config.markers[currentIndex]; var nextMarker = config.current; $('#startFrom').val(nextMarker).trigger('change'); //console.log("Changed ascending to: " + config.ascending); }, 'click #clearLabels': function () { var element = viewportUtils.getActiveViewportElement(); var toolType = 'textMarker'; var toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager; var toolState = toolStateManager.toolState; // We might want to make this a convenience function in cornerstoneTools var stack = cornerstoneTools.getToolState(element, 'stack'); if (stack && stack.data.length && stack.data[0].imageIds.length) { var imageIds = stack.data[0].imageIds; // Clear the tool data for each image in the stack imageIds.forEach(function (imageId) { if (toolState.hasOwnProperty(imageId)) { var toolData = toolState[imageId]; if (toolData.hasOwnProperty(toolType)) { delete toolData[toolType]; } } }); } cornerstone.updateImage(element); }, 'click .closeTextMarkerDialogs': function () { var defaultTool = toolManager.getDefaultTool(); toolManager.setActiveTool(defaultTool); document.getElementById('textMarkerOptionsDialog').close(); $('#spine').removeClass('active'); $('#' + defaultTool).addClass('active'); } }); Template.textMarkerDialogs.onRendered(function () { var optionsDialog = $('#textMarkerOptionsDialog'); optionsDialog.draggable(); dialogPolyfill.registerDialog(optionsDialog.get(0)); var relabelDialog = $('#textMarkerRelabelDialog'); relabelDialog.draggable(); dialogPolyfill.registerDialog(relabelDialog.get(0)); $(document).on('click', function (event) { if (!$(event.target).closest('.select2-wrapper').length) { setTimeout(function () { $('#startFrom, .relabelSelect').select2('close'); }, 200); } }); $(document).on('touchmove', function (event) { if (!$(event.target).closest('.select2-container').length) { setTimeout(function () { $('#startFrom, .relabelSelect').select2('close'); }, 200); } }); $(function () { FastClick.attach(document.body); var $customSelects = $('#startFrom, .relabelSelect'); $customSelects.select2({ /** * Adds needsclick class to all DOM elements in the Select2 results list * so they can be accessible on iOS mobile when FastClick is initiated too. */ templateResult: function (result, container) { if (!result.id) { return result.text; } container.className += ' needsclick'; return result.text; }, placeholder: 'C1', minimumResultsForSearch: -1, theme: 'viewerDropdown' }); /** * Additional to tweaking the templateResult option in Select2, * add needsclick class to all DOM elements in the Select2 container, * so they can be accessible on iOS mobile when FastClick is initiated too. * * More info about needsclick: * https://github.com/ftlabs/fastclick#ignore-certain-elements-with-needsclick * */ $customSelects.each(function (index, el) { $(el).data('select2').$container.find('*').addClass('needsclick'); }); }); }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"seriesQuickSwitch":{"template.seriesQuickSwitch.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/seriesQuickSwitch/template.seriesQuickSwitch.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("seriesQuickSwitch"); Template["seriesQuickSwitch"] = new Template("Template.seriesQuickSwitch", (function() { var view = this; return Blaze.If(function() { return Spacebars.call(view.lookup("shallDisplay")); }, function() { return [ "\n ", HTML.DIV({ class: function() { return [ "series-quick-switch ", Spacebars.mustache(view.lookup("side")), " clearfix noselect" ]; } }, "\n ", HTML.DIV({ class: "series-switch rp-t-1 rp-x-1" }, "\n ", HTML.DIV({ class: "title-label" }, "Series"), "\n ", HTML.DIV({ class: "series-box r-font" }, "\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(view.lookup("seriesItems")), _variable: "seriesItem" }; }, function() { return [ "\n ", HTML.DIV({ class: function() { return [ "series-item ", Spacebars.mustache(Spacebars.dot(view.lookup("seriesItem"), "class")) ]; } }, Blaze.View("lookup:seriesItem.value", function() { return Spacebars.mustache(Spacebars.dot(view.lookup("seriesItem"), "value")); })), "\n " ]; }), "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("series-browser"), scrollStep: Spacebars.call(201) }; }, function() { return Spacebars.include(view.lookupTemplate("scrollArea"), function() { return [ "\n ", HTML.DIV({ class: "clearfix thumbnails-wrapper" }, "\n ", Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("clone"), view.lookup("."), Spacebars.kw({ studyMetadata: Spacebars.dot(view.lookup("instance"), "currentStudy") })); }, function() { return Spacebars.include(view.lookupTemplate("studyBrowserSeries")); }), "\n "), "\n " ]; }); }), "\n "), "\n "), "\n ", HTML.DIV({ class: "study-switch rp-t-1 rp-x-1" }, "\n ", HTML.DIV({ class: "title-label" }, "Study"), "\n ", HTML.DIV({ class: "study-box r-font" }, "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("study-browser"), scrollStep: Spacebars.call(91) }; }, function() { return Spacebars.include(view.lookupTemplate("scrollArea"), function() { return [ "\n ", Blaze._TemplateWith(function() { return { template: Spacebars.call(view.lookup("studyBrowserTemplate")), data: Spacebars.call(Spacebars.dataMustache(view.lookup("clone"), view.lookup("."), Spacebars.kw({ currentStudy: Spacebars.dot(view.lookup("instance"), "currentStudy") }))) }; }, function() { return Spacebars.include(function() { return Spacebars.call(Template.__dynamic); }); }), "\n " ]; }); }), "\n "), "\n "), "\n "), "\n " ]; }); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"seriesQuickSwitch.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var ReactiveVar; module.watch(require("meteor/reactive-var"), { ReactiveVar: function (v) { ReactiveVar = v; } }, 1); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 2); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 3); Template.seriesQuickSwitch.onCreated(function () { var instance = Template.instance(); // Defines the study being shown in the current viewport instance.currentStudy = new ReactiveVar(); // Gets the viewport data for the given viewport index instance.getViewportData = function (viewportIndex) { var layoutManager = OHIF.viewerbase.layoutManager; return layoutManager && layoutManager.viewportData && layoutManager.viewportData[viewportIndex]; }; // Gets the current viewport data var viewportIndex = instance.data.viewportIndex; instance.study = {}; instance.lastStudy = {}; instance.autorun(function () { OHIF.viewerbase.layoutManager.observer.depend(); var viewportData = instance.getViewportData(viewportIndex); // @TypeSafeStudies if (viewportData) { // Finds the current study and return it instance.study = OHIF.viewer.Studies.findBy({ studyInstanceUid: viewportData.studyInstanceUid }); } if (!instance.study) { instance.study = OHIF.viewer.Studies.getElementByIndex(0); } if (!instance.study) { return; } if (instance.study.studyInstanceUid !== instance.lastStudy.studyInstanceUid) { // Change the current study to update the thumbnails instance.currentStudy.set(instance.study); instance.lastStudy = instance.study; } }); }); Template.seriesQuickSwitch.helpers({ shallDisplay: function () { var instance = Template.instance(); var _instance$data = instance.data, rows = _instance$data.rows, columns = _instance$data.columns; return OHIF.viewer.displaySeriesQuickSwitch && rows === 1 && columns <= 2; }, side: function () { var instance = Template.instance(); var _instance$data2 = instance.data, columns = _instance$data2.columns, viewportIndex = _instance$data2.viewportIndex; if (columns === 1) return ''; return viewportIndex === 0 ? 'left' : 'right'; }, seriesItems: function () { var instance = Template.instance(); OHIF.viewerbase.layoutManager.observer.depend(); var viewportIndex = instance.data.viewportIndex; var viewportData = OHIF.viewerbase.layoutManager.viewportData[viewportIndex]; var study = instance.currentStudy.get(); var seriesItems = []; var displaySets = study.displaySets; if (!displaySets.length) { displaySets = OHIF.viewerbase.sortingManager.getDisplaySets(study); study.displaySets = displaySets; study.setDisplaySets(displaySets); study.forEachDisplaySet(function (displaySet) { OHIF.viewerbase.stackManager.makeAndAddStack(study, displaySet); }); } var items = displaySets.length; for (var i = 0; i < items; i++) { var displaySet = displaySets[i]; var item = { "class": '' }; seriesItems.push(item); if (i === 8 && items !== 9) { item.class += ' count'; item.value = items; break; } if (displaySet.displaySetInstanceUid === viewportData.displaySetInstanceUid) { item.class += ' active'; } } return seriesItems; }, studyBrowserTemplate: function () { return OHIF.viewer.quickSwitchStudyBrowserTemplate || 'studyBrowserQuickSwitch'; } }); Template.seriesQuickSwitch.events({ 'mouseenter .series-switch, rescale .series-switch': function (event, instance) { // Control the width of the series browser var $switch = $(event.currentTarget); var $seriesBrowser = $switch.find('.series-browser'); var $seriesQuickSwitch = $switch.closest('.series-quick-switch'); var isRight = $seriesQuickSwitch.hasClass('right'); var switchOffsetLeft = $switch.offset().left; var switchOuterWidth = $switch.outerWidth(); var browserWidth; if (isRight) { browserWidth = $(window).width() - switchOffsetLeft; } else { browserWidth = switchOffsetLeft + switchOuterWidth; } $seriesBrowser.width(browserWidth - browserWidth % 240); var $quickSwitch = instance.$('.series-quick-switch'); if ($quickSwitch.is(':hover')) { $quickSwitch.addClass('series-triggered'); } }, 'mouseleave .series-browser': function (event, instance) { $(event.currentTarget).children('.scrollable').stop().animate({ scrollTop: 0 }, 300, 'swing'); }, 'mouseleave .series-quick-switch': function (event, instance) { $(event.currentTarget).removeClass('series-triggered'); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"studySeriesQuickSwitch":{"template.studySeriesQuickSwitch.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/studySeriesQuickSwitch/template.studySeriesQuickSwitch.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("studySeriesQuickSwitch"); Template["studySeriesQuickSwitch"] = new Template("Template.studySeriesQuickSwitch", (function() { var view = this; return HTML.DIV({ class: function() { return [ "quickSwitchWrapper ", Spacebars.mustache(view.lookup("side")) ]; } }, "\n ", HTML.DIV({ class: function() { return [ "quickSwitch js-quick-switch clearfix ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("eq"), view.lookup("side"), "right"); }, function() { return "rp-l-3"; }), Blaze.If(function() { return Spacebars.dataMustache(view.lookup("eq"), view.lookup("side"), "left"); }, function() { return "rp-r-3"; }) ]; } }, "\n ", HTML.DIV({ class: function() { return [ "switchSection switchSectionStudy rp-t-1 rp-x-1 ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("eq"), view.lookup("side"), "right"); }, function() { return "pull-left"; }, function() { return "pull-right"; }) ]; } }, "\n ", HTML.Raw('
Study
'), "\n ", HTML.DIV({ class: "studySwitch" }, "\n ", HTML.Raw('
'), "\n ", HTML.DIV({ class: "switchHover studyHover clearfix" }, "\n ", HTML.DIV({ class: function() { return [ "scrollArea ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("isMac")); }, function() { return "is-mac"; }) ]; } }, "\n ", Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("clone"), view.lookup("."), Spacebars.kw({ timepointViewType: "key" })); }, function() { return Spacebars.include(view.lookupTemplate("studyTimepointBrowser")); }), "\n "), "\n "), "\n "), "\n "), "\n ", HTML.DIV({ class: function() { return [ "switchSection switchSectionSeries rp-t-1 rp-x-1 ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("eq"), view.lookup("side"), "right"); }, function() { return "pull-left"; }, function() { return "pull-right"; }) ]; } }, "\n ", Blaze.Let({ thumbnailsList: function() { return Spacebars.call(Spacebars.dataMustache(view.lookup("studyThumbnails"), view.lookup("currentStudy"))); } }, function() { return [ "\n ", HTML.DIV({ class: "label" }, "Series"), "\n ", HTML.DIV({ class: "seriesSwitch clearfix" }, "\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(view.lookup("thumbnailsList")), _variable: "thumbnail" }; }, function() { return [ "\n ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("lt"), view.lookup("@index"), 8); }, function() { return [ "\n ", HTML.DIV({ class: function() { return [ "seriesItem ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("eq"), view.lookup("side"), "right"); }, function() { return "pull-left"; }, function() { return "pull-right"; }), " ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("isDisplaySetActive"), Spacebars.dot(view.lookup("thumbnail"), "stack", "displaySetInstanceUid"), view.lookup("viewportIndex")); }, function() { return "active"; }) ]; } }), "\n " ]; }, function() { return [ "\n ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("eq"), view.lookup("@index"), 8); }, function() { return [ "\n ", HTML.DIV({ class: function() { return [ "seriesItem count ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("eq"), view.lookup("side"), "right"); }, function() { return "pull-left"; }, function() { return "pull-right"; }) ]; } }, Blaze.View("lookup:thumbnailsList.length", function() { return Spacebars.mustache(Spacebars.dot(view.lookup("thumbnailsList"), "length")); })), "\n " ]; }), "\n " ]; }), "\n " ]; }), "\n ", HTML.DIV({ class: "switchHover seriesHover clearfix" }, "\n ", HTML.DIV({ class: function() { return [ "scrollArea ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("isMac")); }, function() { return "is-mac"; }) ]; } }, "\n ", HTML.DIV({ class: "thumbnailsWrapper" }, "\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(view.lookup("thumbnailsList")), _variable: "thumbnail" }; }, function() { return [ "\n ", Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("clone"), view.lookup("."), Spacebars.kw({ thumbnail: view.lookup("thumbnail") })); }, function() { return Spacebars.include(view.lookupTemplate("thumbnailEntry")); }), "\n " ]; }), "\n "), "\n "), "\n "), "\n "), "\n " ]; }), "\n "), "\n "), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"studySeriesQuickSwitch.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/studySeriesQuickSwitch/studySeriesQuickSwitch.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var ReactiveVar; module.watch(require("meteor/reactive-var"), { ReactiveVar: function (v) { ReactiveVar = v; } }, 1); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 2); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 3); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 4); Template.studySeriesQuickSwitch.onCreated(function () { var instance = Template.instance(); // Defines the study being shown in the current viewport instance.data.currentStudy = new ReactiveVar(); // Gets the viewport data for the given viewport index instance.getViewportData = function (viewportIndex) { var layoutManager = OHIF.viewerbase.layoutManager; return layoutManager && layoutManager.viewportData && layoutManager.viewportData[viewportIndex]; }; // Gets the current viewport data var viewportIndex = instance.data.viewportIndex; instance.study = {}; instance.lastStudy = {}; instance.autorun(function () { Session.get('LayoutManagerUpdated'); var viewportData = instance.getViewportData(viewportIndex); // @TypeSafeStudies if (viewportData) { // Finds the current study and return it instance.study = OHIF.viewer.Studies.findBy({ studyInstanceUid: viewportData.studyInstanceUid }); } else { instance.study = OHIF.viewer.Studies.getElementByIndex(0); } if (!instance.study) { return; } if (instance.study.studyInstanceUid !== instance.lastStudy.studyInstanceUid) { // Change the current study to update the thumbnails instance.data.currentStudy.set(instance.study); instance.lastStudy = instance.study; } }); }); var checkScrollArea = function (element) { var scrollHeight = element.scrollHeight, offsetHeight = element.offsetHeight, scrollTop = element.scrollTop; var matrix = $(element).find('.thumbnailsWrapper').css('transform'); var translateY = 0; if (matrix && matrix !== 'none') { translateY = parseInt(matrix.match(/-?[\d\.]+/g)[5]); } if (scrollHeight > offsetHeight + scrollTop + translateY) { element.classList.add('show-scroll-indicator-down'); } else { element.classList.remove('show-scroll-indicator-down'); } if (scrollTop > 0) { element.classList.add('show-scroll-indicator-up'); } else { element.classList.remove('show-scroll-indicator-up'); } }; Template.studySeriesQuickSwitch.events({ 'mouseenter .js-quick-switch, mouseenter .js-quick-switch .switchSectionSeries': function (event, instance) { instance.$('.quickSwitchWrapper').addClass('overlay'); $(event.currentTarget).addClass('hover'); instance.$('.scrollArea').each(function (index, scrollAreaElement) { return checkScrollArea(scrollAreaElement); }); }, 'mouseleave .js-quick-switch': function (event, instance) { instance.$('.js-quick-switch, .switchSectionSeries').removeClass('hover'); instance.$('.quickSwitchWrapper').removeClass('overlay'); }, 'click .thumbnailEntry': function (event, instance) { // Close the quick switch if we have selected a series instance.$('.js-quick-switch, .switchSectionSeries').removeClass('hover'); instance.$('.quickSwitchWrapper').removeClass('overlay'); }, 'click .study-browser-item': function (event, instance) { instance.$('.switchSectionSeries').addClass('hover'); }, 'scroll .scrollArea': function (event) { checkScrollArea(event.currentTarget); } }); Template.studySeriesQuickSwitch.helpers({ // Get the current study currentStudy: function () { return Template.instance().data.currentStudy.get(); }, // Check if is Mac OS // This is necessary due to fix scrollbar space only in browsers in Mac OS: // Since Lion version, the scrollbar is visible only when user scrolls a div // As scrollbar is hidden, the space added to hide it in Windows browsers // is not enough in Mac OS. For WebKit (Safari and Chrome in Mac OS) there is a CSS // solution using ::-webkit-scrollbar, but unfortunately doesn't work for Firefox // JS seems to be the only solution for now: // - http://stackoverflow.com/questions/6165472/custom-css-scrollbar-for-firefox/6165489#6165489 // - http://stackoverflow.com/questions/18317634/force-visible-scrollbar-in-firefox-on-mac-os-x/18318273 isMac: function () { return window.navigator.appVersion.indexOf('Mac'); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"studyTimepointBrowser":{"template.studyTimepoint.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/studyTimepointBrowser/template.studyTimepoint.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("studyTimepoint"); Template["studyTimepoint"] = new Template("Template.studyTimepoint", (function() { var view = this; return HTML.DIV({ class: "studyTimepointWrapper" }, "\n ", HTML.DIV({ class: "studyTimepoint" }, "\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(view.lookup("studies")), _variable: "study" }; }, function() { return [ "\n ", Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("clone"), view.lookup("."), Spacebars.kw({ study: view.lookup("study"), active: Spacebars.dataMustache(view.lookup("isActive"), view.lookup("study")) })); }, function() { return Spacebars.include(view.lookupTemplate("studyTimepointStudy")); }), "\n " ]; }), "\n "), "\n "); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"studyTimepoint.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/studyTimepointBrowser/studyTimepoint.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 1); Template.studyTimepoint.onCreated(function () { var instance = Template.instance(); var data = instance.data; instance.isActive = {}; if (data.isUnassociatedStudy === true && data.studyInstanceUids.length === 1) { instance.isActive[data.studyInstanceUids[0]] = true; } }); // Initialize the timepoint wrapper max-height to enable CSS transition Template.studyTimepoint.onRendered(function () { var instance = Template.instance(); var $studies = instance.$('.studyTimepoint'); var $wrapper = $studies.closest('.studyTimepointWrapper'); var $timepoint = $wrapper.closest('.timepoint-item'); var studiesVisible = $studies.is(':visible'); if (!studiesVisible) { $timepoint.addClass('active'); } // Recalculates the timepoint height to make CSS transition smoother $studies.trigger('displayStateChanged'); if (!studiesVisible) { $timepoint.removeClass('active'); } }); Template.studyTimepoint.events({ // Changes the selected study 'selectionChanged .studyTimepoint': function (event, instance, changed) { var $selection = $(changed.selection); // Defines where will be the studies searched var $studiesTarget = instance.$('.studyTimepoint'); // @TypeSafeStudies if (changed.isQuickSwitch) { // Changes the current quick switch study var study = OHIF.viewer.Studies.findBy({ studyInstanceUid: changed.studyInstanceUid }); instance.data.currentStudy.set(study); // Changes the target to toggle the selection in all the studies $studiesTarget = $studiesTarget.closest('.studyTimepointBrowser'); } // Removes selected state from all studies but the triggered study $studiesTarget.find('.study-browser-item').not($selection).removeClass('active'); if (changed.isQuickSwitch) { // Reset active studies map to allow only one active study instance.isActive = {}; // Add selected state for the triggered study $selection.addClass('active'); } else { var $timepoint = instance.$('.studyTimepoint'); // Set the max-height to inherit to be able to expand the wrapper on its full height instance.$('.studyTimepointWrapper').css('max-height', 'inherit'); // Toggle selected state for the triggered study $selection.removeClass('loading'); $selection.toggleClass('active'); // Recalculates the timepoint height to make CSS transition smoother var $thumbnails = $selection.find('.study-browser-series'); $thumbnails.one('transitionend', function () { return $timepoint.trigger('displayStateChanged'); }); } // Set the current study as active instance.isActive[changed.studyInstanceUid] = $selection.hasClass('active'); }, // It should be triggered when the timepoint height is changed 'displayStateChanged .studyTimepoint': function (event, instance) { var $timepoint = $(event.currentTarget); var $wrapper = $timepoint.closest('.studyTimepointWrapper'); // Set the max-height for the wrapper to make CSS transition smoother $wrapper.css('max-height', $timepoint.height()); } }); Template.studyTimepoint.helpers({ isActive: function (study) { var instance = Template.instance(); if (!study.studyInstanceUid) { return; } return instance.isActive[study.studyInstanceUid]; } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"template.studyTimepointBrowser.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/studyTimepointBrowser/template.studyTimepointBrowser.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("studyTimepointBrowser"); Template["studyTimepointBrowser"] = new Template("Template.studyTimepointBrowser", (function() { var view = this; return Blaze.Let({ timepointList: function() { return Spacebars.call(view.lookup("timepoints")); } }, function() { return [ "\n ", HTML.DIV({ class: function() { return [ "studyTimepointBrowser noselect ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("shallShowViewType"), view.lookup("timepointList")); }, function() { return "viewTypeVisible"; }) ]; } }, "\n ", HTML.DIV({ class: "timepointButtonContainer p-t-2" }, "\n ", Blaze._TemplateWith(function() { return Spacebars.call(view.lookup("viewTypeButtonGroupData")); }, function() { return Spacebars.include(view.lookupTemplate("roundedButtonGroup")); }), "\n "), "\n ", HTML.DIV({ class: "studyTimepointScrollArea" }, "\n ", HTML.DIV({ class: "p-x-1" }, "\n ", Blaze.If(function() { return Spacebars.call(Spacebars.dot(view.lookup("timepointList"), "length")); }, function() { return [ "\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(view.lookup("timepointList")), _variable: "timepoint" }; }, function() { return [ "\n ", HTML.DIV({ class: "timepoint-browser-item" }, "\n ", HTML.DIV({ class: "timepoint-item p-y-2" }, "\n ", HTML.DIV({ class: "timepointHeader" }, "\n ", HTML.DIV({ class: "timepoint-details clearfix" }, "\n ", HTML.DIV({ class: "timepoint-title pull-left" }, "\n ", Blaze.View("lookup:timepointApi.title", function() { return Spacebars.mustache(Spacebars.dot(view.lookup("timepointApi"), "title"), view.lookup("timepoint")); }), "\n "), "\n ", HTML.DIV({ class: "timepoint-expand-icon pull-right" }, "\n ", HTML.I({ class: "fa fa-chevron-down" }), "\n "), "\n ", HTML.DIV({ class: "timepoint-date pull-right m-r-1" }, Blaze.View("lookup:formatDA", function() { return Spacebars.mustache(view.lookup("formatDA"), Spacebars.dot(view.lookup("timepoint"), "earliestDate"), "D-MMM-YYYY"); })), "\n "), "\n ", HTML.DIV({ class: "timepoint-summary" }, Blaze.View("lookup:modalitiesSummary", function() { return Spacebars.mustache(view.lookup("modalitiesSummary"), view.lookup("timepoint")); })), "\n "), "\n ", Blaze._TemplateWith(function() { return { studies: Spacebars.call(Spacebars.dataMustache(view.lookup("studies"), view.lookup("timepoint"))), index: Spacebars.call(view.lookup("@index")), viewportIndex: Spacebars.call(Spacebars.dot(view.lookup("."), "viewportIndex")), currentStudy: Spacebars.call(Spacebars.dot(view.lookup("."), "currentStudy")) }; }, function() { return Spacebars.include(view.lookupTemplate("studyTimepoint")); }), "\n "), "\n "), "\n ", HTML.HR(), "\n " ]; }), "\n ", Blaze.If(function() { return Spacebars.dataMustache(view.lookup("and"), Spacebars.dot(view.lookup("."), "currentStudy"), Spacebars.dataMustache(view.lookup("not"), view.lookup("showAdditionalTimepoints")), view.lookup("hasAdditionalTimepoints")); }, function() { return [ "\n ", HTML.DIV({ class: "study-item-box additional" }, "\n Show additional timepoints\n "), "\n " ]; }), "\n " ]; }, function() { return [ "\n ", HTML.DIV({ class: "p-t-2" }, "\n ", Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("clone"), view.lookup("."), Spacebars.kw({ studies: view.lookup("studies") })); }, function() { return Spacebars.include(view.lookupTemplate("studyTimepoint")); }), "\n "), "\n " ]; }), "\n "), "\n "), "\n "), "\n " ]; }); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"studyTimepointBrowser.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/studyTimepointBrowser/studyTimepointBrowser.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var ReactiveVar; module.watch(require("meteor/reactive-var"), { ReactiveVar: function (v) { ReactiveVar = v; } }, 1); var Tracker; module.watch(require("meteor/tracker"), { Tracker: function (v) { Tracker = v; } }, 2); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 3); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 4); var OHIFError; module.watch(require("../../../lib/classes/OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 5); Template.studyTimepointBrowser.onCreated(function () { var instance = Template.instance(); // Reactive variable to control the view type for all or key timepoints instance.timepointViewType = new ReactiveVar(instance.data.timepointViewType); // Defines whether to show all key timepoints or only the current one instance.showAdditionalTimepoints = new ReactiveVar(true); // Return the current study if it's defined instance.getCurrentStudy = function () { return instance.data.currentStudy && instance.data.currentStudy.get(); }; // Get the studies for a specific timepoint instance.getStudies = function (timepoint) { // @TypeSafeStudies if (!timepoint) { return OHIF.viewer.Studies.all(); } return timepoint.studyInstanceUids.map(function (studyInstanceUid) { var query = { studyInstanceUid: studyInstanceUid }; var loadedStudy = OHIF.viewer.Studies.findBy(query); if (loadedStudy) return loadedStudy; var notYetLoaded = OHIF.studylist.collections.Studies.findOne(query); if (notYetLoaded) return notYetLoaded; // const studyData = _.findWhere(timepoint.studiesData, query); // if (studyData) return studyData; throw new OHIFError("No study data available for Study: " + studyInstanceUid); }); }; }); Template.studyTimepointBrowser.onRendered(function () { var instance = Template.instance(); // Collapse all timepoints but first when timepoint view type changes instance.autorun(function () { // Runs this computation every time the timepointViewType is changed var type = instance.timepointViewType.get(); // Removes all active classes to collapse the timepoints and studies instance.$('.timepoint-item, .study-browser-item').removeClass('active'); if (type === 'key' && !instance.data.currentStudy) { // Show only first timepoint expanded for key timepoints instance.$('.timepoint-item:first').addClass('active'); } }); // Expand only the timepoints with loaded studies in viewports var lastStudy; var activeStudiesUids = []; // Wait for rerendering and set the timepoint as active instance.refreshActiveStudies = function () { return Tracker.afterFlush(function () { _.each(activeStudiesUids, function (studyInstanceUid) { instance.$(".study-browser-item[data-uid='" + studyInstanceUid + "']").addClass('active'); }); // Show only first timepoint expanded for key timepoints instance.$('.timepoint-item:first').addClass('active'); }); }; instance.autorun(function () { // Runs this computation every time the current study is changed var currentStudy = instance.data.currentStudy && instance.data.currentStudy.get(); // Stop here if there's no current study set if (!currentStudy) { return; } // Check if the study really changed and update the last study if (currentStudy !== lastStudy) { instance.showAdditionalTimepoints.set(false); lastStudy = currentStudy; activeStudiesUids = [currentStudy.studyInstanceUid]; } instance.refreshActiveStudies(); }); }); Template.studyTimepointBrowser.events({ 'click .timepointHeader': function (event, instance) { var $timepoint = $(event.currentTarget).closest('.timepoint-item'); // Recalculates the timepoint height to make CSS transition smoother $timepoint.find('.studyTimepoint').trigger('displayStateChanged'); // Toggle active class to group/ungroup timepoint studies $timepoint.toggleClass('active'); }, 'click .study-item-box.additional': function (event, instance) { // Show all key timepoints instance.showAdditionalTimepoints.set(true); } }); Template.studyTimepointBrowser.helpers({ // Decides if the timepoint view type switch shall be shown or omitted shallShowViewType: function (timepointList) { var instance = Template.instance(); return timepointList.length && !instance.data.timepointViewType; }, // Returns the button group data for switching between timepoint view types viewTypeButtonGroupData: function () { return { value: Template.instance().timepointViewType, options: [{ value: 'key', text: 'Key Timepoints' }, { value: 'all', text: 'All Timepoints' }] }; }, // Defines whether to show all key timepoints or only the current one showAdditionalTimepoints: function () { return Template.instance().showAdditionalTimepoints.get(); }, hasAdditionalTimepoints: function () { var instance = Template.instance(); var timepointApi = instance.data.timepointApi; var allTimepoints = timepointApi && timepointApi.all(); return allTimepoints && allTimepoints.length > 1; }, // Get the timepoints to be listed timepoints: function () { var instance = Template.instance(); // Get the current study var currentStudy = instance.getCurrentStudy(); // Declare the timepoints var timepointApi = instance.data.timepointApi; var timepoints; if (currentStudy && !instance.showAdditionalTimepoints.get()) { // Show only the current study's timepoint timepoints = timepointApi.study(currentStudy.studyInstanceUid); } else { if (!timepointApi) { // If there is no timepoint API defined whatsoever, this means that there is no // current timepoint ID, so we can just display all of the currently loaded studies // in the study sidebar timepoints = []; } else if (instance.timepointViewType.get() === 'all') { // Show all timepoints timepoints = timepointApi.all(); } else { // Show only key timepoints timepoints = timepointApi.key(); } } // Filter timepoints and show only the current timepoint and previous ones var result = []; var currentTimepoint = timepointApi.current(); if (currentTimepoint) { timepoints.forEach(function (timepoint) { if (timepoint.latestDate.getTime() <= currentTimepoint.latestDate.getTime()) { result.push(timepoint); } }); } // Returns the timepoints return result; }, // Get the studies for a specific timepoint studies: function (timepoint) { return Template.instance().getStudies(timepoint); }, // Build the modalities summary for all timepoint's studies modalitiesSummary: function (timepoint) { var instance = Template.instance(); var studies = instance.getStudies(timepoint); var modalities = {}; studies.forEach(function (study) { var modality = study.modalities || 'UN'; modalities[modality] = modalities[modality] + 1 || 1; }); var result = []; _.each(modalities, function (count, modality) { result.push(count + " " + modality); }); return result.join(', '); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"template.studyTimepointStudy.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/studyTimepointBrowser/template.studyTimepointStudy.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("studyTimepointStudy"); Template["studyTimepointStudy"] = new Template("Template.studyTimepointStudy", (function() { var view = this; return Blaze.Let({ isSidebar: function() { return Spacebars.call(Spacebars.dataMustache(view.lookup("isUndefined"), view.lookup("viewportIndex"))); } }, function() { return [ "\n ", HTML.DIV({ class: function() { return [ "study-browser-item ", Blaze.If(function() { return Spacebars.call(view.lookup("isSidebar")); }, function() { return "studySidebarTimepoint"; }, function() { return "studyQuickSwitchTimepoint"; }), " ", Blaze.If(function() { return Spacebars.call(Spacebars.dot(view.lookup("."), "active")); }, function() { return "active"; }), " ", Blaze.If(function() { return Spacebars.call(view.lookup("isLoading")); }, function() { return "loading"; }) ]; }, "data-uid": function() { return Spacebars.mustache(Spacebars.dot(view.lookup("."), "study", "studyInstanceUid")); } }, "\n ", HTML.DIV({ class: "study-item" }, "\n ", Blaze.If(function() { return Spacebars.call(view.lookup("isLoading")); }, function() { return [ "\n ", Spacebars.include(view.lookupTemplate("loadingText")), "\n " ]; }), "\n ", HTML.DIV({ class: "study-item-box" }, "\n ", HTML.DIV({ class: "study-modality" }, "\n ", HTML.DIV({ class: "study-modality-text", style: function() { return Spacebars.mustache(view.lookup("modalityStyle")); } }, "\n ", Blaze.View("lookup:choose", function() { return Spacebars.mustache(view.lookup("choose"), Spacebars.dot(view.lookup("instance"), "modalities"), "UN"); }), "\n "), "\n "), "\n ", HTML.DIV({ class: "study-text" }, "\n ", HTML.DIV({ class: "study-date" }, Blaze.View("lookup:formatDA", function() { return Spacebars.mustache(view.lookup("formatDA"), Spacebars.dot(view.lookup("instance"), "studyDate"), "D-MMM-YYYY"); })), "\n ", HTML.DIV({ class: "study-description" }, Blaze.View("lookup:instance.studyDescription", function() { return Spacebars.mustache(Spacebars.dot(view.lookup("instance"), "studyDescription")); })), "\n "), "\n "), "\n "), "\n ", Blaze.If(function() { return Spacebars.call(view.lookup("isSidebar")); }, function() { return [ "\n ", HTML.DIV({ class: "study-browser-series" }, "\n ", HTML.DIV({ class: "study-series-container" }, "\n ", Blaze.Each(function() { return { _sequence: Spacebars.dataMustache(view.lookup("studyThumbnails"), Spacebars.dot(view.lookup("."), "study")), _variable: "thumbnail" }; }, function() { return [ "\n ", Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("clone"), view.lookup("."), Spacebars.kw({ thumbnail: view.lookup("thumbnail") })); }, function() { return Spacebars.include(view.lookupTemplate("thumbnailEntry")); }), "\n " ]; }), "\n "), "\n "), "\n " ]; }), "\n "), "\n " ]; }); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"studyTimepointStudy.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/studyTimepointBrowser/studyTimepointStudy.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 1); var ReactiveVar; module.watch(require("meteor/reactive-var"), { ReactiveVar: function (v) { ReactiveVar = v; } }, 2); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 3); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 4); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 5); Template.studyTimepointStudy.onCreated(function () { var instance = Template.instance(); instance.loading = new ReactiveVar(false); var studyMetadata = OHIF.viewerbase.getStudyMetadata(instance.data.study); var firstInstance = studyMetadata.getFirstInstance(); if (firstInstance) { instance.modalities = firstInstance.getRawValue('x00080060'); instance.studyDescription = firstInstance.getRawValue('x00081030'); instance.studyDate = firstInstance.getRawValue('x00080020'); } // Get the current study element instance.getStudyElement = function () { var isGlobal = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var studyInstanceUid = instance.data.study.studyInstanceUid; var selector = ".study-browser-item[data-uid='" + studyInstanceUid + "']"; return isGlobal ? $(selector) : instance.$browser.find(selector); }; instance.isQuickSwitch = function () { return !_.isUndefined(instance.data.viewportIndex); }; // Set the current study as selected in the studies list instance.select = function () { var isQuickSwitch = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var studyInstanceUid = instance.data.study.studyInstanceUid; var $study = instance.getStudyElement(); var $timepoint = $study.closest('.studyTimepoint'); var selectionChanged = { selection: [$study[0]], studyInstanceUid: studyInstanceUid, isQuickSwitch: isQuickSwitch }; $timepoint.trigger('selectionChanged', selectionChanged); }; instance.initializeStudyWrapper = function () { // Stop here if it's a quick switch if (instance.isQuickSwitch()) { return; } var $study = instance.getStudyElement(); var $thumbnails = $study.find('.study-browser-series'); $study.addClass('active'); // If element already has max-height property set, .height() // will return that value, so remove it to recalculate $thumbnails.css('max-height', ''); $thumbnails.css('max-height', $thumbnails.height()); $study.removeClass('active'); // Here we add, remove, and add the active class again because this way // the max-height animation appears smooth to the user. if (instance.data.active) { Meteor.setTimeout(function () { return $study.addClass('active'); }, 1); } }; }); // Initialize the study wrapper max-height to enable CSS transition Template.studyTimepointStudy.onRendered(function () { var instance = Template.instance(); // Keep the study timepoint browser element to manipulate elements even after DOM is removed instance.$browser = instance.$('.study-browser-item').closest('.studyTimepointBrowser'); instance.initializeStudyWrapper(); }); Template.studyTimepointStudy.events({ // Recalculates the timepoint height to make CSS transition smoother 'transitionend .study-browser-series': function (event, instance) { if (event.target === event.currentTarget) { $(event.currentTarget).closest('.studyTimepoint').trigger('displayStateChanged'); } }, // Transfers the active state to the current study 'click .studyQuickSwitchTimepoint .study-item-container': function (event, instance) { instance.select(true); }, // Set loading state 'loadStarted .study-browser-item': function (event, instance) { instance.loading.set(true); }, // Remove loading state and fix the thumbnails wrappers height 'loadEnded .study-browser-item': function (event, instance) { instance.loading.set(false); instance.initializeStudyWrapper(); }, // Changes the current study selection for the clicked study 'click .study-item-box': function (event, instance) { var studyData = instance.data.study; var studyInstanceUid = studyData.studyInstanceUid; var isQuickSwitch = instance.isQuickSwitch(); // @TypeSafeStudies // Check if the study already has series data, // and if not, retrieve it. if (!studyData.seriesList) { var alreadyLoaded = OHIF.viewer.Studies.findBy({ studyInstanceUid: studyInstanceUid }); if (!alreadyLoaded) { var $studies = instance.getStudyElement(true); $studies.trigger('loadStarted'); OHIF.studies.retrieveStudyMetadata(studyInstanceUid).then(function (study) { instance.data.study = study; OHIF.viewer.Studies.insert(study); Meteor.setTimeout(function () { $studies.trigger('loadEnded'); instance.select(isQuickSwitch); }, 1); }).catch(function (error) { OHIF.log.error("There was an error trying to retrieve the study's metadata for studyInstanceUid: " + studyInstanceUid); OHIF.log.error(error.stack); OHIF.log.trace(); }); } else { studyData.seriesList = alreadyLoaded.seriesList; instance.select(isQuickSwitch); } } else { instance.select(isQuickSwitch); } } }); Template.studyTimepointStudy.helpers({ isLoading: function () { // @TypeSafeStudies var instance = Template.instance(); var studyData = instance.data.study; var alreadyLoaded = OHIF.viewer.Studies.findBy({ studyInstanceUid: studyData.studyInstanceUid }); return instance.loading.get() && !alreadyLoaded; }, modalities: function () { var instance = Template.instance(); var modalities = instance.modalities || 'UN'; // Replace backslashes with spaces return modalities.replace(/\\/g, ' '); }, modalityStyle: function () { // Responsively styles the Modality Acronyms for studies // with more than one modality var instance = Template.instance(); var modalities = instance.modalities || 'UN'; var numModalities = modalities.split(/\\/g).length; if (numModalities === 1) { // If we have only one modality, it should take up the whole div. return 'font-size: 1em'; } else if (numModalities === 2) { // If we have two, let them sit side-by-side return 'font-size: 0.75em'; } else { // If we have more than two modalities, change the line height to display multiple rows, // depending on the number of modalities we need to display. var lineHeight = Math.ceil(numModalities / 2) * 1.2; return 'line-height: ' + lineHeight + 'em'; } } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"windowLevelPresets":{"template.form.js":function(){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/windowLevelPresets/template.form.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Template.__checkName("windowLevelPresetsForm"); Template["windowLevelPresetsForm"] = new Template("Template.windowLevelPresetsForm", (function() { var view = this; return Blaze._TemplateWith(function() { return Spacebars.dataMustache(view.lookup("extend"), Spacebars.kw({ api: Spacebars.dot(view.lookup("instance"), "api"), class: "form-themed" })); }, function() { return Spacebars.include(view.lookupTemplate("form"), function() { return [ "\n ", HTML.DIV({ class: "form-content" }, "\n ", HTML.TABLE({ class: "full-width" }, "\n ", HTML.THEAD("\n ", HTML.TR("\n ", HTML.TH({ class: "p-x-1 text-center" }, "Preset"), "\n ", HTML.TH({ class: "p-x-1" }, "Description"), "\n ", HTML.TH({ class: "p-x-1" }, "Window"), "\n ", HTML.TH({ class: "p-x-1" }, "Level"), "\n "), "\n "), "\n ", HTML.TBODY("\n ", Blaze.Each(function() { return { _sequence: Spacebars.call(view.lookup("getPresetsInputInformationList")), _variable: "presetInputInformation" }; }, function() { return [ "\n ", Blaze._TemplateWith(function() { return { base: Spacebars.call("baseTr"), key: Spacebars.call(Spacebars.dataMustache(view.lookup("concat"), view.lookup("@index"))) }; }, function() { return Spacebars.include(view.lookupTemplate("group"), function() { return [ "\n ", HTML.TD({ class: "p-x-1 text-center" }, Blaze.View("lookup:sum", function() { return Spacebars.mustache(view.lookup("sum"), view.lookup("@index"), 1); })), "\n ", HTML.TD({ class: "p-x-1" }, Blaze._TemplateWith(function() { return { key: Spacebars.call("id"), value: Spacebars.call(Spacebars.dot(view.lookup("presetInputInformation"), "id")) }; }, function() { return Spacebars.include(view.lookupTemplate("inputText")); })), "\n ", HTML.TD({ class: "p-x-1" }, Blaze._TemplateWith(function() { return { key: Spacebars.call("ww"), value: Spacebars.call(Spacebars.dataMustache(view.lookup("filterNaN"), Spacebars.dot(view.lookup("presetInputInformation"), "ww"))), dataType: Spacebars.call("Number") }; }, function() { return Spacebars.include(view.lookupTemplate("inputText")); })), "\n ", HTML.TD({ class: "p-x-1" }, Blaze._TemplateWith(function() { return { key: Spacebars.call("wc"), value: Spacebars.call(Spacebars.dataMustache(view.lookup("filterNaN"), Spacebars.dot(view.lookup("presetInputInformation"), "wc"))), dataType: Spacebars.call("Number") }; }, function() { return Spacebars.include(view.lookupTemplate("inputText")); })), "\n " ]; }); }), "\n " ]; }), "\n "), "\n "), "\n "), "\n ", HTML.DIV({ class: "form-buttons clearfix" }, "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("btn btn-danger pull-left"), action: Spacebars.call("resetDefaults") }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return "Reset to Defaults"; }); }), "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("btn btn-primary pull-right"), action: Spacebars.call("save") }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return "Save"; }); }), "\n ", Blaze._TemplateWith(function() { return { class: Spacebars.call("btn btn-secondary pull-right m-r-1"), tagAttributes: Spacebars.call(Spacebars.dataMustache(view.lookup("extend"), "", Spacebars.kw({ "data-dismiss": "modal" }))) }; }, function() { return Spacebars.include(view.lookupTemplate("button"), function() { return "Close"; }); }), "\n "), "\n " ]; }); }); })); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"form.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/components/viewer/windowLevelPresets/form.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 1); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 2); Template.windowLevelPresetsForm.onCreated(function () { var instance = Template.instance(); var wlPresets = OHIF.viewerbase.wlPresets; instance.api = { save: function () { var form = instance.$('form').first().data('component'); var definitions = form.value(); var promise = wlPresets.store(definitions); promise.then(function () { return OHIF.ui.notifications.success({ text: 'The Window/Levels preferences were successfully saved.' }); }); return promise; }, resetDefaults: function () { var dialogOptions = { "class": 'themed', title: 'Reset Window/Levels Presets', message: 'Are you sure you want to reset all the window level presets to their defaults?' }; return OHIF.ui.showDialog('dialogConfirm', dialogOptions).then(function () { return wlPresets.resetDefaults(); }); } }; }); Template.windowLevelPresetsForm.helpers({ getPresetsInputInformationList: function () { OHIF.viewerbase.wlPresets.changeObserver.depend(); return _.toArray(OHIF.viewer.wlPresets); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }}}},"collections.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/collections.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var OHIF; module.watch(require("../namespace"), { OHIF: function (v) { OHIF = v; } }, 1); var TypeSafeCollection; module.watch(require("./lib/classes/TypeSafeCollection"), { TypeSafeCollection: function (v) { TypeSafeCollection = v; } }, 2); // Create main Studies collection which will be used across the entire viewer... var Studies = new TypeSafeCollection(); // Make it publicly available on "OHIF.viewer" namespace... OHIF.viewer.Studies = Studies; // Create main StudyMetadataList collection which will be used across the entire viewer... var StudyMetadataList = new TypeSafeCollection(); // Make it publicly available on "OHIF.viewer" namespace... OHIF.viewer.StudyMetadataList = StudyMetadataList; // Subscriptions... Meteor.subscribe('studyImportStatus'); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"index.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/index.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Viewerbase; module.watch(require("../namespace"), { Viewerbase: function (v) { Viewerbase = v; } }, 0); module.watch(require("./collections")); module.watch(require("./lib/debugReactivity")); var getElementIfNotEmpty; module.watch(require("./lib/getElementIfNotEmpty"), { getElementIfNotEmpty: function (v) { getElementIfNotEmpty = v; } }, 1); var getStackDataIfNotEmpty; module.watch(require("./lib/getStackDataIfNotEmpty"), { getStackDataIfNotEmpty: function (v) { getStackDataIfNotEmpty = v; } }, 2); var switchToImageRelative; module.watch(require("./lib/switchToImageRelative"), { switchToImageRelative: function (v) { switchToImageRelative = v; } }, 3); var switchToImageByIndex; module.watch(require("./lib/switchToImageByIndex"), { switchToImageByIndex: function (v) { switchToImageByIndex = v; } }, 4); var getFrameOfReferenceUID; module.watch(require("./lib/getFrameOfReferenceUID"), { getFrameOfReferenceUID: function (v) { getFrameOfReferenceUID = v; } }, 5); var getImageIdForImagePath; module.watch(require("./lib/getImageIdForImagePath"), { getImageIdForImagePath: function (v) { getImageIdForImagePath = v; } }, 6); var updateCrosshairsSynchronizer; module.watch(require("./lib/updateCrosshairsSynchronizer"), { updateCrosshairsSynchronizer: function (v) { updateCrosshairsSynchronizer = v; } }, 7); var getImageId; module.watch(require("./lib/getImageId"), { getImageId: function (v) { getImageId = v; } }, 8); var setActiveViewport; module.watch(require("./lib/setActiveViewport"), { setActiveViewport: function (v) { setActiveViewport = v; } }, 9); var setFocusToActiveViewport; module.watch(require("./lib/setFocusToActiveViewport"), { setFocusToActiveViewport: function (v) { setFocusToActiveViewport = v; } }, 10); var getWADORSImageId; module.watch(require("./lib/getWADORSImageId"), { getWADORSImageId: function (v) { getWADORSImageId = v; } }, 11); var updateAllViewports; module.watch(require("./lib/updateAllViewports"), { updateAllViewports: function (v) { updateAllViewports = v; } }, 12); var sortStudy; module.watch(require("./lib/sortStudy"), { sortStudy: function (v) { sortStudy = v; } }, 13); var updateMetaDataManager; module.watch(require("./lib/updateMetaDataManager"), { updateMetaDataManager: function (v) { updateMetaDataManager = v; } }, 14); var updateOrientationMarkers; module.watch(require("./lib/updateOrientationMarkers"), { updateOrientationMarkers: function (v) { updateOrientationMarkers = v; } }, 15); var isImage; module.watch(require("./lib/isImage"), { isImage: function (v) { isImage = v; } }, 16); var getInstanceClassDefaultViewport, setInstanceClassDefaultViewportFunction; module.watch(require("./lib/instanceClassSpecificViewport"), { getInstanceClassDefaultViewport: function (v) { getInstanceClassDefaultViewport = v; }, setInstanceClassDefaultViewportFunction: function (v) { setInstanceClassDefaultViewportFunction = v; } }, 17); var displayReferenceLines; module.watch(require("./lib/displayReferenceLines"), { displayReferenceLines: function (v) { displayReferenceLines = v; } }, 18); var getStudyMetadata; module.watch(require("./lib/getStudyMetadata"), { getStudyMetadata: function (v) { getStudyMetadata = v; } }, 19); var imageViewerViewportData; module.watch(require("./lib/imageViewerViewportData"), { imageViewerViewportData: function (v) { imageViewerViewportData = v; } }, 20); var panelNavigation; module.watch(require("./lib/panelNavigation"), { panelNavigation: function (v) { panelNavigation = v; } }, 21); var prepareViewerData; module.watch(require("./lib/prepareViewerData"), { prepareViewerData: function (v) { prepareViewerData = v; } }, 22); var renderViewer; module.watch(require("./lib/renderViewer"), { renderViewer: function (v) { renderViewer = v; } }, 23); var WLPresets; module.watch(require("./lib/WLPresets"), { WLPresets: function (v) { WLPresets = v; } }, 24); var hotkeyUtils; module.watch(require("./lib/hotkeyUtils"), { hotkeyUtils: function (v) { hotkeyUtils = v; } }, 25); var viewportOverlayUtils; module.watch(require("./lib/viewportOverlayUtils"), { viewportOverlayUtils: function (v) { viewportOverlayUtils = v; } }, 26); var viewportUtils; module.watch(require("./lib/viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 27); var thumbnailDragHandlers; module.watch(require("./lib/thumbnailDragHandlers"), { thumbnailDragHandlers: function (v) { thumbnailDragHandlers = v; } }, 28); var dialogUtils; module.watch(require("./lib/dialogUtils"), { dialogUtils: function (v) { dialogUtils = v; } }, 29); var unloadHandlers; module.watch(require("./lib/unloadHandlers"), { unloadHandlers: function (v) { unloadHandlers = v; } }, 30); var sortingManager; module.watch(require("./lib/sortingManager"), { sortingManager: function (v) { sortingManager = v; } }, 31); var crosshairsSynchronizers; module.watch(require("./lib/crosshairsSynchronizers"), { crosshairsSynchronizers: function (v) { crosshairsSynchronizers = v; } }, 32); var annotateTextUtils; module.watch(require("./lib/annotateTextUtils"), { annotateTextUtils: function (v) { annotateTextUtils = v; } }, 33); var textMarkerUtils; module.watch(require("./lib/textMarkerUtils"), { textMarkerUtils: function (v) { textMarkerUtils = v; } }, 34); var createStacks; module.watch(require("./lib/createStacks"), { createStacks: function (v) { createStacks = v; } }, 35); var StackManager; module.watch(require("./lib/StackManager"), { StackManager: function (v) { StackManager = v; } }, 36); var toolManager; module.watch(require("./lib/toolManager"), { toolManager: function (v) { toolManager = v; } }, 37); var helpers; module.watch(require("./lib/helpers/"), { helpers: function (v) { helpers = v; } }, 38); var sopClassDictionary; module.watch(require("./lib/sopClassDictionary"), { sopClassDictionary: function (v) { sopClassDictionary = v; } }, 39); var DICOMTagDescriptions; module.watch(require("./lib/DICOMTagDescriptions"), { DICOMTagDescriptions: function (v) { DICOMTagDescriptions = v; } }, 40); var ImageSet; module.watch(require("./lib/classes/ImageSet"), { ImageSet: function (v) { ImageSet = v; } }, 41); var LayoutManager; module.watch(require("./lib/classes/LayoutManager"), { LayoutManager: function (v) { LayoutManager = v; } }, 42); var StudyPrefetcher; module.watch(require("./lib/classes/StudyPrefetcher"), { StudyPrefetcher: function (v) { StudyPrefetcher = v; } }, 43); var ResizeViewportManager; module.watch(require("./lib/classes/ResizeViewportManager"), { ResizeViewportManager: function (v) { ResizeViewportManager = v; } }, 44); var StudyLoadingListener; module.watch(require("./lib/classes/StudyLoadingListener"), { StudyLoadingListener: function (v) { StudyLoadingListener = v; } }, 45); var StackLoadingListener; module.watch(require("./lib/classes/StudyLoadingListener"), { StackLoadingListener: function (v) { StackLoadingListener = v; } }, 46); var DICOMFileLoadingListener; module.watch(require("./lib/classes/StudyLoadingListener"), { DICOMFileLoadingListener: function (v) { DICOMFileLoadingListener = v; } }, 47); var StudyMetadata; module.watch(require("./lib/classes/metadata/StudyMetadata"), { StudyMetadata: function (v) { StudyMetadata = v; } }, 48); var SeriesMetadata; module.watch(require("./lib/classes/metadata/SeriesMetadata"), { SeriesMetadata: function (v) { SeriesMetadata = v; } }, 49); var InstanceMetadata; module.watch(require("./lib/classes/metadata/InstanceMetadata"), { InstanceMetadata: function (v) { InstanceMetadata = v; } }, 50); var StudySummary; module.watch(require("./lib/classes/metadata/StudySummary"), { StudySummary: function (v) { StudySummary = v; } }, 51); var plugins; module.watch(require("./lib/classes/plugins/"), { plugins: function (v) { plugins = v; } }, 52); var TypeSafeCollection; module.watch(require("./lib/classes/TypeSafeCollection"), { TypeSafeCollection: function (v) { TypeSafeCollection = v; } }, 53); var OHIFError; module.watch(require("./lib/classes/OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 54); var StackImagePositionOffsetSynchronizer; module.watch(require("./lib/classes/StackImagePositionOffsetSynchronizer"), { StackImagePositionOffsetSynchronizer: function (v) { StackImagePositionOffsetSynchronizer = v; } }, 55); var StudyMetadataSource; module.watch(require("./lib/classes/StudyMetadataSource"), { StudyMetadataSource: function (v) { StudyMetadataSource = v; } }, 56); Viewerbase.getElementIfNotEmpty = getElementIfNotEmpty; // getStackDataIfNotEmpty Viewerbase.getStackDataIfNotEmpty = getStackDataIfNotEmpty; // switchToImageRelative Viewerbase.switchToImageRelative = switchToImageRelative; // switchToImageByIndex Viewerbase.switchToImageByIndex = switchToImageByIndex; // getFrameOfReferenceUID Viewerbase.getFrameOfReferenceUID = getFrameOfReferenceUID; // getImageIdForImagePath Viewerbase.getImageIdForImagePath = getImageIdForImagePath; // updateCrosshairsSynchronizer Viewerbase.updateCrosshairsSynchronizer = updateCrosshairsSynchronizer; // getImageId Viewerbase.getImageId = getImageId; // setActiveViewport Viewerbase.setActiveViewport = setActiveViewport; // setFocusToActiveViewport Viewerbase.setFocusToActiveViewport = setFocusToActiveViewport; // getWADORSImageId Viewerbase.getWADORSImageId = getWADORSImageId; // updateAllViewports Viewerbase.updateAllViewports = updateAllViewports; // sortStudy Viewerbase.sortStudy = sortStudy; // updateMetaDataManager Viewerbase.updateMetaDataManager = updateMetaDataManager; // updateOrientationMarkers Viewerbase.updateOrientationMarkers = updateOrientationMarkers; // isImage Viewerbase.isImage = isImage; // getInstanceClassDefaultViewport, setInstanceClassDefaultViewportFunction Viewerbase.getInstanceClassDefaultViewport = getInstanceClassDefaultViewport; Viewerbase.setInstanceClassDefaultViewportFunction = setInstanceClassDefaultViewportFunction; // displayReferenceLines Viewerbase.displayReferenceLines = displayReferenceLines; // getStudyMetadata Viewerbase.getStudyMetadata = getStudyMetadata; /** * Exported Namespaces (sub-namespaces) */ // imageViewerViewportData.* Viewerbase.imageViewerViewportData = imageViewerViewportData; // panelNavigation.* Viewerbase.panelNavigation = panelNavigation; // prepareViewerData Viewerbase.prepareViewerData = prepareViewerData; // renderViewer Viewerbase.renderViewer = renderViewer; // WLPresets.* Viewerbase.wlPresets = WLPresets; // hotkeyUtils.* Viewerbase.hotkeyUtils = hotkeyUtils; // viewportOverlayUtils.* Viewerbase.viewportOverlayUtils = viewportOverlayUtils; // viewportUtils.* Viewerbase.viewportUtils = viewportUtils; // thumbnailDragHandlers.* Viewerbase.thumbnailDragHandlers = thumbnailDragHandlers; // dialogUtils.* Viewerbase.dialogUtils = dialogUtils; // unloadHandlers.* Viewerbase.unloadHandlers = unloadHandlers; // sortingManager.* Viewerbase.sortingManager = sortingManager; // crosshairsSynchronizers.* Viewerbase.crosshairsSynchronizers = crosshairsSynchronizers; // annotateTextUtils.* Viewerbase.annotateTextUtils = annotateTextUtils; // textMarkerUtils.* Viewerbase.textMarkerUtils = textMarkerUtils; // createStacks.* Viewerbase.createStacks = createStacks; /** * Exported Singletons */ // StackManager as "stackManager" (since it's a plain object instance, the exported name starts with a lowercase letter) Viewerbase.stackManager = StackManager; // toolManager Viewerbase.toolManager = toolManager; /** * Exported Helpers */ Viewerbase.helpers = helpers; /** * Exported Collections */ // sopClassDictionary Viewerbase.sopClassDictionary = sopClassDictionary; // dicomTagDescriptions Viewerbase.DICOMTagDescriptions = DICOMTagDescriptions; /** * Exported Classes */ // ImageSet Viewerbase.ImageSet = ImageSet; // LayoutManager Viewerbase.LayoutManager = LayoutManager; // StudyPrefetcher Viewerbase.StudyPrefetcher = StudyPrefetcher; // ResizeViewportManager Viewerbase.ResizeViewportManager = ResizeViewportManager; // StudyLoadingListener Viewerbase.StudyLoadingListener = StudyLoadingListener; // StackLoadingListener Viewerbase.StackLoadingListener = StackLoadingListener; // DICOMFileLoadingListener Viewerbase.DICOMFileLoadingListener = DICOMFileLoadingListener; // StudyMetadata, SeriesMetadata, InstanceMetadata Viewerbase.metadata = { StudyMetadata: StudyMetadata, SeriesMetadata: SeriesMetadata, InstanceMetadata: InstanceMetadata, StudySummary: StudySummary }; Viewerbase.plugins = plugins; // TypeSafeCollection Viewerbase.TypeSafeCollection = TypeSafeCollection; // OHIFError Viewerbase.OHIFError = OHIFError; // StackImagePositionOffsetSynchronizer Viewerbase.StackImagePositionOffsetSynchronizer = StackImagePositionOffsetSynchronizer; // StudyMetadataSource Viewerbase.StudyMetadataSource = StudyMetadataSource; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"lib":{"DICOMTagDescriptions.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/DICOMTagDescriptions.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); module.export({ DICOMTagDescriptions: function () { return DICOMTagDescriptions; } }); var NUMBER = 'number'; var STRING = 'string'; var REGEX_TAG = /^x[0-9a-fx]{8}$/; var DICOMTagDescriptions = Object.create(Object.prototype, { _descriptions: { configurable: false, enumerable: false, writable: false, value: Object.create(null) }, tagNumberToString: { configurable: false, enumerable: true, writable: false, value: function () { function tagNumberToString(tag) { var string; // by default, undefined is returned... if (this.isValidTagNumber(tag)) { // if it's a number, build its hexadecimal representation... string = 'x' + ('00000000' + tag.toString(16)).substr(-8); } return string; } return tagNumberToString; }() }, isValidTagNumber: { configurable: false, enumerable: true, writable: false, value: function () { function isValidTagNumber(tag) { return (0, _typeof2.default)(tag) === NUMBER && tag >= 0 && tag <= 0xFFFFFFFF; } return isValidTagNumber; }() }, isValidTag: { configurable: false, enumerable: true, writable: false, value: function () { function isValidTag(tag) { return (0, _typeof2.default)(tag) === STRING ? REGEX_TAG.test(tag) : this.isValidTagNumber(tag); } return isValidTag; }() }, find: { configurable: false, enumerable: true, writable: false, value: function () { function find(name) { var description; // by default, undefined is returned... if ((0, _typeof2.default)(name) !== STRING) { // if it's a number, a tag string will be returned... name = this.tagNumberToString(name); } if ((0, _typeof2.default)(name) === STRING) { description = this._descriptions[name]; } return description; } return find; }() }, init: { configurable: false, enumerable: true, writable: false, value: function () { function init(descriptionMap) { var _hasOwn = Object.prototype.hasOwnProperty; var _descriptions = this._descriptions; for (var tag in meteorBabelHelpers.sanitizeForInObject(descriptionMap)) { if (_hasOwn.call(descriptionMap, tag)) { if (!this.isValidTag(tag)) { // Skip in case tag is not valid... console.info("DICOMTagDescriptions: Invalid tag \"" + tag + "\"..."); continue; } if (tag in _descriptions) { // Skip in case the tag is duplicated... console.info("DICOMTagDescriptions: Duplicated tag \"" + tag + "\"..."); continue; } // Save keyword... var keyword = descriptionMap[tag]; // Create a description entry and freeze it... var entry = Object.create(null); entry.tag = tag; entry.keyword = keyword; Object.freeze(entry); // Add tag references to entry... _descriptions[tag] = entry; // Add keyword references to entry (if not present already)... if (keyword in _descriptions) { var currentEntry = _descriptions[keyword]; console.info("DICOMTagDescriptions: Using <" + currentEntry.tag + "," + currentEntry.keyword + "> instead of <" + entry.tag + "," + entry.keyword + "> for keyword \"" + keyword + "\"..."); } else { _descriptions[keyword] = entry; } } } // Freeze internal description map... Object.freeze(_descriptions); // Freeze itself... Object.freeze(this); } return init; }() } }); /** * Map with DICOM Tag Descriptions */ var initialTagDescriptionMap = { x00020000: 'FileMetaInfoGroupLength', x00020001: 'FileMetaInfoVersion', x00020002: 'MediaStorageSOPClassUID', x00020003: 'MediaStorageSOPInstanceUID', x00020010: 'TransferSyntaxUID', x00020012: 'ImplementationClassUID', x00020013: 'ImplementationVersionName', x00020016: 'SourceApplicationEntityTitle', x00020100: 'PrivateInformationCreatorUID', x00020102: 'PrivateInformation', x00041130: 'FileSetID', x00041141: 'FileSetDescriptorFileID', x00041142: 'SpecificCharacterSetOfFile', x00041200: 'FirstDirectoryRecordOffset', x00041202: 'LastDirectoryRecordOffset', x00041212: 'FileSetConsistencyFlag', x00041220: 'DirectoryRecordSequence', x00041400: 'OffsetOfNextDirectoryRecord', x00041410: 'RecordInUseFlag', x00041420: 'LowerLevelDirectoryEntityOffset', x00041430: 'DirectoryRecordType', x00041432: 'PrivateRecordUID', x00041500: 'ReferencedFileID', x00041504: 'MRDRDirectoryRecordOffset', x00041510: 'ReferencedSOPClassUIDInFile', x00041511: 'ReferencedSOPInstanceUIDInFile', x00041512: 'ReferencedTransferSyntaxUIDInFile', x0004151a: 'ReferencedRelatedSOPClassUIDInFile', x00041600: 'NumberOfReferences', x00080000: 'IdentifyingGroupLength', x00080001: 'LengthToEnd', x00080005: 'SpecificCharacterSet', x00080006: 'LanguageCodeSequence', x00080008: 'ImageType', x00080010: 'RecognitionCode', x00080012: 'InstanceCreationDate', x00080013: 'InstanceCreationTime', x00080014: 'InstanceCreatorUID', x00080016: 'SOPClassUID', x00080018: 'SOPInstanceUID', x0008001a: 'RelatedGeneralSOPClassUID', x0008001b: 'OriginalSpecializedSOPClassUID', x00080020: 'StudyDate', x00080021: 'SeriesDate', x00080022: 'AcquisitionDate', x00080023: 'ContentDate', x00080024: 'OverlayDate', x00080025: 'CurveDate', x0008002a: 'AcquisitionDateTime', x00080030: 'StudyTime', x00080031: 'SeriesTime', x00080032: 'AcquisitionTime', x00080033: 'ContentTime', x00080034: 'OverlayTime', x00080035: 'CurveTime', x00080040: 'DataSetType', x00080041: 'DataSetSubtype', x00080042: 'NuclearMedicineSeriesType', x00080050: 'AccessionNumber', x00080052: 'QueryRetrieveLevel', x00080054: 'RetrieveAETitle', x00080056: 'InstanceAvailability', x00080058: 'FailedSOPInstanceUIDList', x00080060: 'Modality', x00080061: 'ModalitiesInStudy', x00080062: 'SOPClassesInStudy', x00080064: 'ConversionType', x00080068: 'PresentationIntentType', x00080070: 'Manufacturer', x00080080: 'InstitutionName', x00080081: 'InstitutionAddress', x00080082: 'InstitutionCodeSequence', x00080090: 'ReferringPhysicianName', x00080092: 'ReferringPhysicianAddress', x00080094: 'ReferringPhysicianTelephoneNumber', x00080096: 'ReferringPhysicianIDSequence', x00080100: 'CodeValue', x00080102: 'CodingSchemeDesignator', x00080103: 'CodingSchemeVersion', x00080104: 'CodeMeaning', x00080105: 'MappingResource', x00080106: 'ContextGroupVersion', x00080107: 'ContextGroupLocalVersion', x0008010b: 'ContextGroupExtensionFlag', x0008010c: 'CodingSchemeUID', x0008010d: 'ContextGroupExtensionCreatorUID', x0008010f: 'ContextIdentifier', x00080110: 'CodingSchemeIDSequence', x00080112: 'CodingSchemeRegistry', x00080114: 'CodingSchemeExternalID', x00080115: 'CodingSchemeName', x00080116: 'CodingSchemeResponsibleOrganization', x00080117: 'ContextUID', x00080201: 'TimezoneOffsetFromUTC', x00081000: 'NetworkID', x00081010: 'StationName', x00081030: 'StudyDescription', x00081032: 'ProcedureCodeSequence', x0008103e: 'SeriesDescription', x00081040: 'InstitutionalDepartmentName', x00081048: 'PhysiciansOfRecord', x00081049: 'PhysiciansOfRecordIDSequence', x00081050: 'PerformingPhysicianName', x00081052: 'PerformingPhysicianIDSequence', x00081060: 'NameOfPhysicianReadingStudy', x00081062: 'PhysicianReadingStudyIDSequence', x00081070: 'OperatorsName', x00081072: 'OperatorIDSequence', x00081080: 'AdmittingDiagnosesDescription', x00081084: 'AdmittingDiagnosesCodeSequence', x00081090: 'ManufacturersModelName', x00081100: 'ReferencedResultsSequence', x00081110: 'ReferencedStudySequence', x00081111: 'ReferencedPerformedProcedureStepSequence', x00081115: 'ReferencedSeriesSequence', x00081120: 'ReferencedPatientSequence', x00081125: 'ReferencedVisitSequence', x00081130: 'ReferencedOverlaySequence', x0008113a: 'ReferencedWaveformSequence', x00081140: 'ReferencedImageSequence', x00081145: 'ReferencedCurveSequence', x0008114a: 'ReferencedInstanceSequence', x00081150: 'ReferencedSOPClassUID', x00081155: 'ReferencedSOPInstanceUID', x0008115a: 'SOPClassesSupported', x00081160: 'ReferencedFrameNumber', x00081161: 'SimpleFrameList', x00081162: 'CalculatedFrameList', x00081163: 'TimeRange', x00081164: 'FrameExtractionSequence', x00081195: 'TransactionUID', x00081197: 'FailureReason', x00081198: 'FailedSOPSequence', x00081199: 'ReferencedSOPSequence', x00081200: 'OtherReferencedStudiesSequence', x00081250: 'RelatedSeriesSequence', x00082110: 'LossyImageCompressionRetired', x00082111: 'DerivationDescription', x00082112: 'SourceImageSequence', x00082120: 'StageName', x00082122: 'StageNumber', x00082124: 'NumberOfStages', x00082127: 'ViewName', x00082128: 'ViewNumber', x00082129: 'NumberOfEventTimers', x0008212a: 'NumberOfViewsInStage', x00082130: 'EventElapsedTimes', x00082132: 'EventTimerNames', x00082133: 'EventTimerSequence', x00082134: 'EventTimeOffset', x00082135: 'EventCodeSequence', x00082142: 'StartTrim', x00082143: 'StopTrim', x00082144: 'RecommendedDisplayFrameRate', x00082200: 'TransducerPosition', x00082204: 'TransducerOrientation', x00082208: 'AnatomicStructure', x00082218: 'AnatomicRegionSequence', x00082220: 'AnatomicRegionModifierSequence', x00082228: 'PrimaryAnatomicStructureSequence', x00082229: 'AnatomicStructureOrRegionSequence', x00082230: 'AnatomicStructureModifierSequence', x00082240: 'TransducerPositionSequence', x00082242: 'TransducerPositionModifierSequence', x00082244: 'TransducerOrientationSequence', x00082246: 'TransducerOrientationModifierSeq', x00082253: 'AnatomicEntrancePortalCodeSeqTrial', x00082255: 'AnatomicApproachDirCodeSeqTrial', x00082256: 'AnatomicPerspectiveDescrTrial', x00082257: 'AnatomicPerspectiveCodeSeqTrial', x00083001: 'AlternateRepresentationSequence', x00083010: 'IrradiationEventUID', x00084000: 'IdentifyingComments', x00089007: 'FrameType', x00089092: 'ReferencedImageEvidenceSequence', x00089121: 'ReferencedRawDataSequence', x00089123: 'CreatorVersionUID', x00089124: 'DerivationImageSequence', x00089154: 'SourceImageEvidenceSequence', x00089205: 'PixelPresentation', x00089206: 'VolumetricProperties', x00089207: 'VolumeBasedCalculationTechnique', x00089208: 'ComplexImageComponent', x00089209: 'AcquisitionContrast', x00089215: 'DerivationCodeSequence', x00089237: 'GrayscalePresentationStateSequence', x00089410: 'ReferencedOtherPlaneSequence', x00089458: 'FrameDisplaySequence', x00089459: 'RecommendedDisplayFrameRateInFloat', x00089460: 'SkipFrameRangeFlag', // x00091001: 'FullFidelity', // x00091002: 'SuiteID', // x00091004: 'ProductID', // x00091027: 'ImageActualDate', // x00091030: 'ServiceID', // x00091031: 'MobileLocationNumber', // x000910e3: 'EquipmentUID', // x000910e6: 'GenesisVersionNow', // x000910e7: 'ExamRecordChecksum', // x000910e9: 'ActualSeriesDataTimeStamp', x00100000: 'PatientGroupLength', x00100010: 'PatientName', x00100020: 'PatientID', x00100021: 'IssuerOfPatientID', x00100022: 'TypeOfPatientID', x00100030: 'PatientBirthDate', x00100032: 'PatientBirthTime', x00100040: 'PatientSex', x00100050: 'PatientInsurancePlanCodeSequence', x00100101: 'PatientPrimaryLanguageCodeSeq', x00100102: 'PatientPrimaryLanguageCodeModSeq', x00101000: 'OtherPatientIDs', x00101001: 'OtherPatientNames', x00101002: 'OtherPatientIDsSequence', x00101005: 'PatientBirthName', x00101010: 'PatientAge', x00101020: 'PatientSize', x00101030: 'PatientWeight', x00101040: 'PatientAddress', x00101050: 'InsurancePlanIdentification', x00101060: 'PatientMotherBirthName', x00101080: 'MilitaryRank', x00101081: 'BranchOfService', x00101090: 'MedicalRecordLocator', x00102000: 'MedicalAlerts', x00102110: 'Allergies', x00102150: 'CountryOfResidence', x00102152: 'RegionOfResidence', x00102154: 'PatientTelephoneNumbers', x00102160: 'EthnicGroup', x00102180: 'Occupation', x001021a0: 'SmokingStatus', x001021b0: 'AdditionalPatientHistory', x001021c0: 'PregnancyStatus', x001021d0: 'LastMenstrualDate', x001021f0: 'PatientReligiousPreference', x00102201: 'PatientSpeciesDescription', x00102202: 'PatientSpeciesCodeSequence', x00102203: 'PatientSexNeutered', x00102210: 'AnatomicalOrientationType', x00102292: 'PatientBreedDescription', x00102293: 'PatientBreedCodeSequence', x00102294: 'BreedRegistrationSequence', x00102295: 'BreedRegistrationNumber', x00102296: 'BreedRegistryCodeSequence', x00102297: 'ResponsiblePerson', x00102298: 'ResponsiblePersonRole', x00102299: 'ResponsibleOrganization', x00104000: 'PatientComments', x00109431: 'ExaminedBodyThickness', x00111010: 'PatientStatus', x00120010: 'ClinicalTrialSponsorName', x00120020: 'ClinicalTrialProtocolID', x00120021: 'ClinicalTrialProtocolName', x00120030: 'ClinicalTrialSiteID', x00120031: 'ClinicalTrialSiteName', x00120040: 'ClinicalTrialSubjectID', x00120042: 'ClinicalTrialSubjectReadingID', x00120050: 'ClinicalTrialTimePointID', x00120051: 'ClinicalTrialTimePointDescription', x00120060: 'ClinicalTrialCoordinatingCenter', x00120062: 'PatientIdentityRemoved', x00120063: 'DeidentificationMethod', x00120064: 'DeidentificationMethodCodeSequence', x00120071: 'ClinicalTrialSeriesID', x00120072: 'ClinicalTrialSeriesDescription', x00120084: 'DistributionType', x00120085: 'ConsentForDistributionFlag', x00180000: 'AcquisitionGroupLength', x00180010: 'ContrastBolusAgent', x00180012: 'ContrastBolusAgentSequence', x00180014: 'ContrastBolusAdministrationRoute', x00180015: 'BodyPartExamined', x00180020: 'ScanningSequence', x00180021: 'SequenceVariant', x00180022: 'ScanOptions', x00180023: 'MRAcquisitionType', x00180024: 'SequenceName', x00180025: 'AngioFlag', x00180026: 'InterventionDrugInformationSeq', x00180027: 'InterventionDrugStopTime', x00180028: 'InterventionDrugDose', x00180029: 'InterventionDrugSequence', x0018002a: 'AdditionalDrugSequence', x00180030: 'Radionuclide', x00180031: 'Radiopharmaceutical', x00180032: 'EnergyWindowCenterline', x00180033: 'EnergyWindowTotalWidth', x00180034: 'InterventionDrugName', x00180035: 'InterventionDrugStartTime', x00180036: 'InterventionSequence', x00180037: 'TherapyType', x00180038: 'InterventionStatus', x00180039: 'TherapyDescription', x0018003a: 'InterventionDescription', x00180040: 'CineRate', x00180042: 'InitialCineRunState', x00180050: 'SliceThickness', x00180060: 'KVP', x00180070: 'CountsAccumulated', x00180071: 'AcquisitionTerminationCondition', x00180072: 'EffectiveDuration', x00180073: 'AcquisitionStartCondition', x00180074: 'AcquisitionStartConditionData', x00180075: 'AcquisitionEndConditionData', x00180080: 'RepetitionTime', x00180081: 'EchoTime', x00180082: 'InversionTime', x00180083: 'NumberOfAverages', x00180084: 'ImagingFrequency', x00180085: 'ImagedNucleus', x00180086: 'EchoNumber', x00180087: 'MagneticFieldStrength', x00180088: 'SpacingBetweenSlices', x00180089: 'NumberOfPhaseEncodingSteps', x00180090: 'DataCollectionDiameter', x00180091: 'EchoTrainLength', x00180093: 'PercentSampling', x00180094: 'PercentPhaseFieldOfView', x00180095: 'PixelBandwidth', x00181000: 'DeviceSerialNumber', x00181002: 'DeviceUID', x00181003: 'DeviceID', x00181004: 'PlateID', x00181005: 'GeneratorID', x00181006: 'GridID', x00181007: 'CassetteID', x00181008: 'GantryID', x00181010: 'SecondaryCaptureDeviceID', x00181011: 'HardcopyCreationDeviceID', x00181012: 'DateOfSecondaryCapture', x00181014: 'TimeOfSecondaryCapture', x00181016: 'SecondaryCaptureDeviceManufacturer', x00181017: 'HardcopyDeviceManufacturer', x00181018: 'SecondaryCaptureDeviceModelName', x00181019: 'SecondaryCaptureDeviceSoftwareVers', x0018101a: 'HardcopyDeviceSoftwareVersion', x0018101b: 'HardcopyDeviceModelName', x00181020: 'SoftwareVersion', x00181022: 'VideoImageFormatAcquired', x00181023: 'DigitalImageFormatAcquired', x00181030: 'ProtocolName', x00181040: 'ContrastBolusRoute', x00181041: 'ContrastBolusVolume', x00181042: 'ContrastBolusStartTime', x00181043: 'ContrastBolusStopTime', x00181044: 'ContrastBolusTotalDose', x00181045: 'SyringeCounts', x00181046: 'ContrastFlowRate', x00181047: 'ContrastFlowDuration', x00181048: 'ContrastBolusIngredient', x00181049: 'ContrastBolusConcentration', x00181050: 'SpatialResolution', x00181060: 'TriggerTime', x00181061: 'TriggerSourceOrType', x00181062: 'NominalInterval', x00181063: 'FrameTime', x00181064: 'CardiacFramingType', x00181065: 'FrameTimeVector', x00181066: 'FrameDelay', x00181067: 'ImageTriggerDelay', x00181068: 'MultiplexGroupTimeOffset', x00181069: 'TriggerTimeOffset', x0018106a: 'SynchronizationTrigger', x0018106c: 'SynchronizationChannel', x0018106e: 'TriggerSamplePosition', x00181070: 'RadiopharmaceuticalRoute', x00181071: 'RadiopharmaceuticalVolume', x00181072: 'RadiopharmaceuticalStartTime', x00181073: 'RadiopharmaceuticalStopTime', x00181074: 'RadionuclideTotalDose', x00181075: 'RadionuclideHalfLife', x00181076: 'RadionuclidePositronFraction', x00181077: 'RadiopharmaceuticalSpecActivity', x00181078: 'RadiopharmaceuticalStartDateTime', x00181079: 'RadiopharmaceuticalStopDateTime', x00181080: 'BeatRejectionFlag', x00181081: 'LowRRValue', x00181082: 'HighRRValue', x00181083: 'IntervalsAcquired', x00181084: 'IntervalsRejected', x00181085: 'PVCRejection', x00181086: 'SkipBeats', x00181088: 'HeartRate', x00181090: 'CardiacNumberOfImages', x00181094: 'TriggerWindow', x00181100: 'ReconstructionDiameter', x00181110: 'DistanceSourceToDetector', x00181111: 'DistanceSourceToPatient', x00181114: 'EstimatedRadiographicMagnification', x00181120: 'GantryDetectorTilt', x00181121: 'GantryDetectorSlew', x00181130: 'TableHeight', x00181131: 'TableTraverse', x00181134: 'TableMotion', x00181135: 'TableVerticalIncrement', x00181136: 'TableLateralIncrement', x00181137: 'TableLongitudinalIncrement', x00181138: 'TableAngle', x0018113a: 'TableType', x00181140: 'RotationDirection', x00181141: 'AngularPosition', x00181142: 'RadialPosition', x00181143: 'ScanArc', x00181144: 'AngularStep', x00181145: 'CenterOfRotationOffset', x00181146: 'RotationOffset', x00181147: 'FieldOfViewShape', x00181149: 'FieldOfViewDimensions', x00181150: 'ExposureTime', x00181151: 'XRayTubeCurrent', x00181152: 'Exposure', x00181153: 'ExposureInMicroAmpSec', x00181154: 'AveragePulseWidth', x00181155: 'RadiationSetting', x00181156: 'RectificationType', x0018115a: 'RadiationMode', x0018115e: 'ImageAreaDoseProduct', x00181160: 'FilterType', x00181161: 'TypeOfFilters', x00181162: 'IntensifierSize', x00181164: 'ImagerPixelSpacing', x00181166: 'Grid', x00181170: 'GeneratorPower', x00181180: 'CollimatorGridName', x00181181: 'CollimatorType', x00181182: 'FocalDistance', x00181183: 'XFocusCenter', x00181184: 'YFocusCenter', x00181190: 'FocalSpots', x00181191: 'AnodeTargetMaterial', x001811a0: 'BodyPartThickness', x001811a2: 'CompressionForce', x00181200: 'DateOfLastCalibration', x00181201: 'TimeOfLastCalibration', x00181210: 'ConvolutionKernel', x00181240: 'UpperLowerPixelValues', x00181242: 'ActualFrameDuration', x00181243: 'CountRate', x00181244: 'PreferredPlaybackSequencing', x00181250: 'ReceiveCoilName', x00181251: 'TransmitCoilName', x00181260: 'PlateType', x00181261: 'PhosphorType', x00181300: 'ScanVelocity', x00181301: 'WholeBodyTechnique', x00181302: 'ScanLength', x00181310: 'AcquisitionMatrix', x00181312: 'InPlanePhaseEncodingDirection', x00181314: 'FlipAngle', x00181315: 'VariableFlipAngleFlag', x00181316: 'SAR', x00181318: 'DB-Dt', x00181400: 'AcquisitionDeviceProcessingDescr', x00181401: 'AcquisitionDeviceProcessingCode', x00181402: 'CassetteOrientation', x00181403: 'CassetteSize', x00181404: 'ExposuresOnPlate', x00181405: 'RelativeXRayExposure', x00181450: 'ColumnAngulation', x00181460: 'TomoLayerHeight', x00181470: 'TomoAngle', x00181480: 'TomoTime', x00181490: 'TomoType', x00181491: 'TomoClass', x00181495: 'NumberOfTomosynthesisSourceImages', x00181500: 'PositionerMotion', x00181508: 'PositionerType', x00181510: 'PositionerPrimaryAngle', x00181511: 'PositionerSecondaryAngle', x00181520: 'PositionerPrimaryAngleIncrement', x00181521: 'PositionerSecondaryAngleIncrement', x00181530: 'DetectorPrimaryAngle', x00181531: 'DetectorSecondaryAngle', x00181600: 'ShutterShape', x00181602: 'ShutterLeftVerticalEdge', x00181604: 'ShutterRightVerticalEdge', x00181606: 'ShutterUpperHorizontalEdge', x00181608: 'ShutterLowerHorizontalEdge', x00181610: 'CenterOfCircularShutter', x00181612: 'RadiusOfCircularShutter', x00181620: 'VerticesOfPolygonalShutter', x00181622: 'ShutterPresentationValue', x00181623: 'ShutterOverlayGroup', x00181624: 'ShutterPresentationColorCIELabVal', x00181700: 'CollimatorShape', x00181702: 'CollimatorLeftVerticalEdge', x00181704: 'CollimatorRightVerticalEdge', x00181706: 'CollimatorUpperHorizontalEdge', x00181708: 'CollimatorLowerHorizontalEdge', x00181710: 'CenterOfCircularCollimator', x00181712: 'RadiusOfCircularCollimator', x00181720: 'VerticesOfPolygonalCollimator', x00181800: 'AcquisitionTimeSynchronized', x00181801: 'TimeSource', x00181802: 'TimeDistributionProtocol', x00181803: 'NTPSourceAddress', x00182001: 'PageNumberVector', x00182002: 'FrameLabelVector', x00182003: 'FramePrimaryAngleVector', x00182004: 'FrameSecondaryAngleVector', x00182005: 'SliceLocationVector', x00182006: 'DisplayWindowLabelVector', x00182010: 'NominalScannedPixelSpacing', x00182020: 'DigitizingDeviceTransportDirection', x00182030: 'RotationOfScannedFilm', x00183100: 'IVUSAcquisition', x00183101: 'IVUSPullbackRate', x00183102: 'IVUSGatedRate', x00183103: 'IVUSPullbackStartFrameNumber', x00183104: 'IVUSPullbackStopFrameNumber', x00183105: 'LesionNumber', x00184000: 'AcquisitionComments', x00185000: 'OutputPower', x00185010: 'TransducerData', x00185012: 'FocusDepth', x00185020: 'ProcessingFunction', x00185021: 'PostprocessingFunction', x00185022: 'MechanicalIndex', x00185024: 'BoneThermalIndex', x00185026: 'CranialThermalIndex', x00185027: 'SoftTissueThermalIndex', x00185028: 'SoftTissueFocusThermalIndex', x00185029: 'SoftTissueSurfaceThermalIndex', x00185030: 'DynamicRange', x00185040: 'TotalGain', x00185050: 'DepthOfScanField', x00185100: 'PatientPosition', x00185101: 'ViewPosition', x00185104: 'ProjectionEponymousNameCodeSeq', x00185210: 'ImageTransformationMatrix', x00185212: 'ImageTranslationVector', x00186000: 'Sensitivity', x00186011: 'SequenceOfUltrasoundRegions', x00186012: 'RegionSpatialFormat', x00186014: 'RegionDataType', x00186016: 'RegionFlags', x00186018: 'RegionLocationMinX0', x0018601a: 'RegionLocationMinY0', x0018601c: 'RegionLocationMaxX1', x0018601e: 'RegionLocationMaxY1', x00186020: 'ReferencePixelX0', x00186022: 'ReferencePixelY0', x00186024: 'PhysicalUnitsXDirection', x00186026: 'PhysicalUnitsYDirection', x00186028: 'ReferencePixelPhysicalValueX', x0018602a: 'ReferencePixelPhysicalValueY', x0018602c: 'PhysicalDeltaX', x0018602e: 'PhysicalDeltaY', x00186030: 'TransducerFrequency', x00186031: 'TransducerType', x00186032: 'PulseRepetitionFrequency', x00186034: 'DopplerCorrectionAngle', x00186036: 'SteeringAngle', x00186038: 'DopplerSampleVolumeXPosRetired', x00186039: 'DopplerSampleVolumeXPosition', x0018603a: 'DopplerSampleVolumeYPosRetired', x0018603b: 'DopplerSampleVolumeYPosition', x0018603c: 'TMLinePositionX0Retired', x0018603d: 'TMLinePositionX0', x0018603e: 'TMLinePositionY0Retired', x0018603f: 'TMLinePositionY0', x00186040: 'TMLinePositionX1Retired', x00186041: 'TMLinePositionX1', x00186042: 'TMLinePositionY1Retired', x00186043: 'TMLinePositionY1', x00186044: 'PixelComponentOrganization', x00186046: 'PixelComponentMask', x00186048: 'PixelComponentRangeStart', x0018604a: 'PixelComponentRangeStop', x0018604c: 'PixelComponentPhysicalUnits', x0018604e: 'PixelComponentDataType', x00186050: 'NumberOfTableBreakPoints', x00186052: 'TableOfXBreakPoints', x00186054: 'TableOfYBreakPoints', x00186056: 'NumberOfTableEntries', x00186058: 'TableOfPixelValues', x0018605a: 'TableOfParameterValues', x00186060: 'RWaveTimeVector', x00187000: 'DetectorConditionsNominalFlag', x00187001: 'DetectorTemperature', x00187004: 'DetectorType', x00187005: 'DetectorConfiguration', x00187006: 'DetectorDescription', x00187008: 'DetectorMode', x0018700a: 'DetectorID', x0018700c: 'DateOfLastDetectorCalibration', x0018700e: 'TimeOfLastDetectorCalibration', x00187010: 'DetectorExposuresSinceCalibration', x00187011: 'DetectorExposuresSinceManufactured', x00187012: 'DetectorTimeSinceLastExposure', x00187014: 'DetectorActiveTime', x00187016: 'DetectorActiveOffsetFromExposure', x0018701a: 'DetectorBinning', x00187020: 'DetectorElementPhysicalSize', x00187022: 'DetectorElementSpacing', x00187024: 'DetectorActiveShape', x00187026: 'DetectorActiveDimensions', x00187028: 'DetectorActiveOrigin', x0018702a: 'DetectorManufacturerName', x0018702b: 'DetectorManufacturersModelName', x00187030: 'FieldOfViewOrigin', x00187032: 'FieldOfViewRotation', x00187034: 'FieldOfViewHorizontalFlip', x00187040: 'GridAbsorbingMaterial', x00187041: 'GridSpacingMaterial', x00187042: 'GridThickness', x00187044: 'GridPitch', x00187046: 'GridAspectRatio', x00187048: 'GridPeriod', x0018704c: 'GridFocalDistance', x00187050: 'FilterMaterial', x00187052: 'FilterThicknessMinimum', x00187054: 'FilterThicknessMaximum', x00187060: 'ExposureControlMode', x00187062: 'ExposureControlModeDescription', x00187064: 'ExposureStatus', x00187065: 'PhototimerSetting', x00188150: 'ExposureTimeInMicroSec', x00188151: 'XRayTubeCurrentInMicroAmps', x00189004: 'ContentQualification', x00189005: 'PulseSequenceName', x00189006: 'MRImagingModifierSequence', x00189008: 'EchoPulseSequence', x00189009: 'InversionRecovery', x00189010: 'FlowCompensation', x00189011: 'MultipleSpinEcho', x00189012: 'MultiPlanarExcitation', x00189014: 'PhaseContrast', x00189015: 'TimeOfFlightContrast', x00189016: 'Spoiling', x00189017: 'SteadyStatePulseSequence', x00189018: 'EchoPlanarPulseSequence', x00189019: 'TagAngleFirstAxis', x00189020: 'MagnetizationTransfer', x00189021: 'T2Preparation', x00189022: 'BloodSignalNulling', x00189024: 'SaturationRecovery', x00189025: 'SpectrallySelectedSuppression', x00189026: 'SpectrallySelectedExcitation', x00189027: 'SpatialPresaturation', x00189028: 'Tagging', x00189029: 'OversamplingPhase', x00189030: 'TagSpacingFirstDimension', x00189032: 'GeometryOfKSpaceTraversal', x00189033: 'SegmentedKSpaceTraversal', x00189034: 'RectilinearPhaseEncodeReordering', x00189035: 'TagThickness', x00189036: 'PartialFourierDirection', x00189037: 'CardiacSynchronizationTechnique', x00189041: 'ReceiveCoilManufacturerName', x00189042: 'MRReceiveCoilSequence', x00189043: 'ReceiveCoilType', x00189044: 'QuadratureReceiveCoil', x00189045: 'MultiCoilDefinitionSequence', x00189046: 'MultiCoilConfiguration', x00189047: 'MultiCoilElementName', x00189048: 'MultiCoilElementUsed', x00189049: 'MRTransmitCoilSequence', x00189050: 'TransmitCoilManufacturerName', x00189051: 'TransmitCoilType', x00189052: 'SpectralWidth', x00189053: 'ChemicalShiftReference', x00189054: 'VolumeLocalizationTechnique', x00189058: 'MRAcquisitionFrequencyEncodeSteps', x00189059: 'Decoupling', x00189060: 'DecoupledNucleus', x00189061: 'DecouplingFrequency', x00189062: 'DecouplingMethod', x00189063: 'DecouplingChemicalShiftReference', x00189064: 'KSpaceFiltering', x00189065: 'TimeDomainFiltering', x00189066: 'NumberOfZeroFills', x00189067: 'BaselineCorrection', x00189069: 'ParallelReductionFactorInPlane', x00189070: 'CardiacRRIntervalSpecified', x00189073: 'AcquisitionDuration', x00189074: 'FrameAcquisitionDateTime', x00189075: 'DiffusionDirectionality', x00189076: 'DiffusionGradientDirectionSequence', x00189077: 'ParallelAcquisition', x00189078: 'ParallelAcquisitionTechnique', x00189079: 'InversionTimes', x00189080: 'MetaboliteMapDescription', x00189081: 'PartialFourier', x00189082: 'EffectiveEchoTime', x00189083: 'MetaboliteMapCodeSequence', x00189084: 'ChemicalShiftSequence', x00189085: 'CardiacSignalSource', x00189087: 'DiffusionBValue', x00189089: 'DiffusionGradientOrientation', x00189090: 'VelocityEncodingDirection', x00189091: 'VelocityEncodingMinimumValue', x00189093: 'NumberOfKSpaceTrajectories', x00189094: 'CoverageOfKSpace', x00189095: 'SpectroscopyAcquisitionPhaseRows', x00189096: 'ParallelReductFactorInPlaneRetired', x00189098: 'TransmitterFrequency', x00189100: 'ResonantNucleus', x00189101: 'FrequencyCorrection', x00189103: 'MRSpectroscopyFOV-GeometrySequence', x00189104: 'SlabThickness', x00189105: 'SlabOrientation', x00189106: 'MidSlabPosition', x00189107: 'MRSpatialSaturationSequence', x00189112: 'MRTimingAndRelatedParametersSeq', x00189114: 'MREchoSequence', x00189115: 'MRModifierSequence', x00189117: 'MRDiffusionSequence', x00189118: 'CardiacTriggerSequence', x00189119: 'MRAveragesSequence', x00189125: 'MRFOV-GeometrySequence', x00189126: 'VolumeLocalizationSequence', x00189127: 'SpectroscopyAcquisitionDataColumns', x00189147: 'DiffusionAnisotropyType', x00189151: 'FrameReferenceDateTime', x00189152: 'MRMetaboliteMapSequence', x00189155: 'ParallelReductionFactorOutOfPlane', x00189159: 'SpectroscopyOutOfPlanePhaseSteps', x00189166: 'BulkMotionStatus', x00189168: 'ParallelReductionFactSecondInPlane', x00189169: 'CardiacBeatRejectionTechnique', x00189170: 'RespiratoryMotionCompTechnique', x00189171: 'RespiratorySignalSource', x00189172: 'BulkMotionCompensationTechnique', x00189173: 'BulkMotionSignalSource', x00189174: 'ApplicableSafetyStandardAgency', x00189175: 'ApplicableSafetyStandardDescr', x00189176: 'OperatingModeSequence', x00189177: 'OperatingModeType', x00189178: 'OperatingMode', x00189179: 'SpecificAbsorptionRateDefinition', x00189180: 'GradientOutputType', x00189181: 'SpecificAbsorptionRateValue', x00189182: 'GradientOutput', x00189183: 'FlowCompensationDirection', x00189184: 'TaggingDelay', x00189185: 'RespiratoryMotionCompTechDescr', x00189186: 'RespiratorySignalSourceID', x00189195: 'ChemicalShiftsMinIntegrateLimitHz', x00189196: 'ChemicalShiftsMaxIntegrateLimitHz', x00189197: 'MRVelocityEncodingSequence', x00189198: 'FirstOrderPhaseCorrection', x00189199: 'WaterReferencedPhaseCorrection', x00189200: 'MRSpectroscopyAcquisitionType', x00189214: 'RespiratoryCyclePosition', x00189217: 'VelocityEncodingMaximumValue', x00189218: 'TagSpacingSecondDimension', x00189219: 'TagAngleSecondAxis', x00189220: 'FrameAcquisitionDuration', x00189226: 'MRImageFrameTypeSequence', x00189227: 'MRSpectroscopyFrameTypeSequence', x00189231: 'MRAcqPhaseEncodingStepsInPlane', x00189232: 'MRAcqPhaseEncodingStepsOutOfPlane', x00189234: 'SpectroscopyAcqPhaseColumns', x00189236: 'CardiacCyclePosition', x00189239: 'SpecificAbsorptionRateSequence', x00189240: 'RFEchoTrainLength', x00189241: 'GradientEchoTrainLength', x00189295: 'ChemicalShiftsMinIntegrateLimitPPM', x00189296: 'ChemicalShiftsMaxIntegrateLimitPPM', x00189301: 'CTAcquisitionTypeSequence', x00189302: 'AcquisitionType', x00189303: 'TubeAngle', x00189304: 'CTAcquisitionDetailsSequence', x00189305: 'RevolutionTime', x00189306: 'SingleCollimationWidth', x00189307: 'TotalCollimationWidth', x00189308: 'CTTableDynamicsSequence', x00189309: 'TableSpeed', x00189310: 'TableFeedPerRotation', x00189311: 'SpiralPitchFactor', x00189312: 'CTGeometrySequence', x00189313: 'DataCollectionCenterPatient', x00189314: 'CTReconstructionSequence', x00189315: 'ReconstructionAlgorithm', x00189316: 'ConvolutionKernelGroup', x00189317: 'ReconstructionFieldOfView', x00189318: 'ReconstructionTargetCenterPatient', x00189319: 'ReconstructionAngle', x00189320: 'ImageFilter', x00189321: 'CTExposureSequence', x00189322: 'ReconstructionPixelSpacing', x00189323: 'ExposureModulationType', x00189324: 'EstimatedDoseSaving', x00189325: 'CTXRayDetailsSequence', x00189326: 'CTPositionSequence', x00189327: 'TablePosition', x00189328: 'ExposureTimeInMilliSec', x00189329: 'CTImageFrameTypeSequence', x00189330: 'XRayTubeCurrentInMilliAmps', x00189332: 'ExposureInMilliAmpSec', x00189333: 'ConstantVolumeFlag', x00189334: 'FluoroscopyFlag', x00189335: 'SourceToDataCollectionCenterDist', x00189337: 'ContrastBolusAgentNumber', x00189338: 'ContrastBolusIngredientCodeSeq', x00189340: 'ContrastAdministrationProfileSeq', x00189341: 'ContrastBolusUsageSequence', x00189342: 'ContrastBolusAgentAdministered', x00189343: 'ContrastBolusAgentDetected', x00189344: 'ContrastBolusAgentPhase', x00189345: 'CTDIvol', x00189346: 'CTDIPhantomTypeCodeSequence', x00189351: 'CalciumScoringMassFactorPatient', x00189352: 'CalciumScoringMassFactorDevice', x00189353: 'EnergyWeightingFactor', x00189360: 'CTAdditionalXRaySourceSequence', x00189401: 'ProjectionPixelCalibrationSequence', x00189402: 'DistanceSourceToIsocenter', x00189403: 'DistanceObjectToTableTop', x00189404: 'ObjectPixelSpacingInCenterOfBeam', x00189405: 'PositionerPositionSequence', x00189406: 'TablePositionSequence', x00189407: 'CollimatorShapeSequence', x00189412: 'XA-XRFFrameCharacteristicsSequence', x00189417: 'FrameAcquisitionSequence', x00189420: 'XRayReceptorType', x00189423: 'AcquisitionProtocolName', x00189424: 'AcquisitionProtocolDescription', x00189425: 'ContrastBolusIngredientOpaque', x00189426: 'DistanceReceptorPlaneToDetHousing', x00189427: 'IntensifierActiveShape', x00189428: 'IntensifierActiveDimensions', x00189429: 'PhysicalDetectorSize', x00189430: 'PositionOfIsocenterProjection', x00189432: 'FieldOfViewSequence', x00189433: 'FieldOfViewDescription', x00189434: 'ExposureControlSensingRegionsSeq', x00189435: 'ExposureControlSensingRegionShape', x00189436: 'ExposureControlSensRegionLeftEdge', x00189437: 'ExposureControlSensRegionRightEdge', x00189440: 'CenterOfCircExposControlSensRegion', x00189441: 'RadiusOfCircExposControlSensRegion', x00189447: 'ColumnAngulationPatient', x00189449: 'BeamAngle', x00189451: 'FrameDetectorParametersSequence', x00189452: 'CalculatedAnatomyThickness', x00189455: 'CalibrationSequence', x00189456: 'ObjectThicknessSequence', x00189457: 'PlaneIdentification', x00189461: 'FieldOfViewDimensionsInFloat', x00189462: 'IsocenterReferenceSystemSequence', x00189463: 'PositionerIsocenterPrimaryAngle', x00189464: 'PositionerIsocenterSecondaryAngle', x00189465: 'PositionerIsocenterDetRotAngle', x00189466: 'TableXPositionToIsocenter', x00189467: 'TableYPositionToIsocenter', x00189468: 'TableZPositionToIsocenter', x00189469: 'TableHorizontalRotationAngle', x00189470: 'TableHeadTiltAngle', x00189471: 'TableCradleTiltAngle', x00189472: 'FrameDisplayShutterSequence', x00189473: 'AcquiredImageAreaDoseProduct', x00189474: 'CArmPositionerTabletopRelationship', x00189476: 'XRayGeometrySequence', x00189477: 'IrradiationEventIDSequence', x00189504: 'XRay3DFrameTypeSequence', x00189506: 'ContributingSourcesSequence', x00189507: 'XRay3DAcquisitionSequence', x00189508: 'PrimaryPositionerScanArc', x00189509: 'SecondaryPositionerScanArc', x00189510: 'PrimaryPositionerScanStartAngle', x00189511: 'SecondaryPositionerScanStartAngle', x00189514: 'PrimaryPositionerIncrement', x00189515: 'SecondaryPositionerIncrement', x00189516: 'StartAcquisitionDateTime', x00189517: 'EndAcquisitionDateTime', x00189524: 'ApplicationName', x00189525: 'ApplicationVersion', x00189526: 'ApplicationManufacturer', x00189527: 'AlgorithmType', x00189528: 'AlgorithmDescription', x00189530: 'XRay3DReconstructionSequence', x00189531: 'ReconstructionDescription', x00189538: 'PerProjectionAcquisitionSequence', x00189601: 'DiffusionBMatrixSequence', x00189602: 'DiffusionBValueXX', x00189603: 'DiffusionBValueXY', x00189604: 'DiffusionBValueXZ', x00189605: 'DiffusionBValueYY', x00189606: 'DiffusionBValueYZ', x00189607: 'DiffusionBValueZZ', x00189701: 'DecayCorrectionDateTime', x00189715: 'StartDensityThreshold', x00189722: 'TerminationTimeThreshold', x00189725: 'DetectorGeometry', x00189727: 'AxialDetectorDimension', x00189735: 'PETPositionSequence', x00189739: 'NumberOfIterations', x00189740: 'NumberOfSubsets', x00189751: 'PETFrameTypeSequence', x00189756: 'ReconstructionType', x00189758: 'DecayCorrected', x00189759: 'AttenuationCorrected', x00189760: 'ScatterCorrected', x00189761: 'DeadTimeCorrected', x00189762: 'GantryMotionCorrected', x00189763: 'PatientMotionCorrected', x00189765: 'RandomsCorrected', x00189767: 'SensitivityCalibrated', x00189801: 'DepthsOfFocus', x00189804: 'ExclusionStartDatetime', x00189805: 'ExclusionDuration', x00189807: 'ImageDataTypeSequence', x00189808: 'DataType', x0018980b: 'AliasedDataType', x0018a001: 'ContributingEquipmentSequence', x0018a002: 'ContributionDateTime', x0018a003: 'ContributionDescription', // x00191002: 'NumberOfCellsIInDetector', // x00191003: 'CellNumberAtTheta', // x00191004: 'CellSpacing', // x0019100f: 'HorizFrameOfRef', // x00191011: 'SeriesContrast', // x00191012: 'LastPseq', // x00191013: 'StartNumberForBaseline', // x00191014: 'EndNumberForBaseline', // x00191015: 'StartNumberForEnhancedScans', // x00191016: 'EndNumberForEnhancedScans', // x00191017: 'SeriesPlane', // x00191018: 'FirstScanRas', // x00191019: 'FirstScanLocation', // x0019101a: 'LastScanRas', // x0019101b: 'LastScanLoc', // x0019101e: 'DisplayFieldOfView', // x00191023: 'TableSpeed', // x00191024: 'MidScanTime', // x00191025: 'MidScanFlag', // x00191026: 'DegreesOfAzimuth', // x00191027: 'GantryPeriod', // x0019102a: 'XRayOnPosition', // x0019102b: 'XRayOffPosition', // x0019102c: 'NumberOfTriggers', // x0019102e: 'AngleOfFirstView', // x0019102f: 'TriggerFrequency', // x00191039: 'ScanFOVType', // x00191040: 'StatReconFlag', // x00191041: 'ComputeType', // x00191042: 'SegmentNumber', // x00191043: 'TotalSegmentsRequested', // x00191044: 'InterscanDelay', // x00191047: 'ViewCompressionFactor', // x0019104a: 'TotalNoOfRefChannels', // x0019104b: 'DataSizeForScanData', // x00191052: 'ReconPostProcflag', // x00191057: 'CTWaterNumber', // x00191058: 'CTBoneNumber', // x0019105a: 'AcquisitionDuration', // x0019105e: 'NumberOfChannels', // x0019105f: 'IncrementBetweenChannels', // x00191060: 'StartingView', // x00191061: 'NumberOfViews', // x00191062: 'IncrementBetweenViews', // x0019106a: 'DependantOnNoViewsProcessed', // x0019106b: 'FieldOfViewInDetectorCells', // x00191070: 'ValueOfBackProjectionButton', // x00191071: 'SetIfFatqEstimatesWereUsed', // x00191072: 'ZChanAvgOverViews', // x00191073: 'AvgOfLeftRefChansOverViews', // x00191074: 'MaxLeftChanOverViews', // x00191075: 'AvgOfRightRefChansOverViews', // x00191076: 'MaxRightChanOverViews', // x0019107d: 'SecondEcho', // x0019107e: 'NumberOfEchoes', // x0019107f: 'TableDelta', // x00191081: 'Contiguous', // x00191084: 'PeakSAR', // x00191085: 'MonitorSAR', // x00191087: 'CardiacRepetitionTime', // x00191088: 'ImagesPerCardiacCycle', // x0019108a: 'ActualReceiveGainAnalog', // x0019108b: 'ActualReceiveGainDigital', // x0019108d: 'DelayAfterTrigger', // x0019108f: 'Swappf', // x00191090: 'PauseInterval', // x00191091: 'PulseTime', // x00191092: 'SliceOffsetOnFreqAxis', // x00191093: 'CenterFrequency', // x00191094: 'TransmitGain', // x00191095: 'AnalogReceiverGain', // x00191096: 'DigitalReceiverGain', // x00191097: 'BitmapDefiningCVs', // x00191098: 'CenterFreqMethod', // x0019109b: 'PulseSeqMode', // x0019109c: 'PulseSeqName', // x0019109d: 'PulseSeqDate', // x0019109e: 'InternalPulseSeqName', // x0019109f: 'TransmittingCoil', // x001910a0: 'SurfaceCoilType', // x001910a1: 'ExtremityCoilFlag', // x001910a2: 'RawDataRunNumber', // x001910a3: 'CalibratedFieldStrength', // x001910a4: 'SATFatWaterBone', // x001910a5: 'ReceiveBandwidth', // x001910a7: 'UserData01', // x001910a8: 'UserData02', // x001910a9: 'UserData03', // x001910aa: 'UserData04', // x001910ab: 'UserData05', // x001910ac: 'UserData06', // x001910ad: 'UserData07', // x001910ae: 'UserData08', // x001910af: 'UserData09', // x001910b0: 'UserData10', // x001910b1: 'UserData11', // x001910b2: 'UserData12', // x001910b3: 'UserData13', // x001910b4: 'UserData14', // x001910b5: 'UserData15', // x001910b6: 'UserData16', // x001910b7: 'UserData17', // x001910b8: 'UserData18', // x001910b9: 'UserData19', // x001910ba: 'UserData20', // x001910bb: 'UserData21', // x001910bc: 'UserData22', // x001910bd: 'UserData23', // x001910be: 'ProjectionAngle', // x001910c0: 'SaturationPlanes', // x001910c1: 'SurfaceCoilIntensity', // x001910c2: 'SATLocationR', // x001910c3: 'SATLocationL', // x001910c4: 'SATLocationA', // x001910c5: 'SATLocationP', // x001910c6: 'SATLocationH', // x001910c7: 'SATLocationF', // x001910c8: 'SATThicknessR-L', // x001910c9: 'SATThicknessA-P', // x001910ca: 'SATThicknessH-F', // x001910cb: 'PrescribedFlowAxis', // x001910cc: 'VelocityEncoding', // x001910cd: 'ThicknessDisclaimer', // x001910ce: 'PrescanType', // x001910cf: 'PrescanStatus', // x001910d0: 'RawDataType', // x001910d2: 'ProjectionAlgorithm', // x001910d3: 'ProjectionAlgorithm', // x001910d5: 'FractionalEcho', // x001910d6: 'PrepPulse', // x001910d7: 'CardiacPhases', // x001910d8: 'VariableEchoflag', // x001910d9: 'ConcatenatedSAT', // x001910da: 'ReferenceChannelUsed', // x001910db: 'BackProjectorCoefficient', // x001910dc: 'PrimarySpeedCorrectionUsed', // x001910dd: 'OverrangeCorrectionUsed', // x001910de: 'DynamicZAlphaValue', // x001910df: 'UserData', // x001910e0: 'UserData', // x001910e2: 'VelocityEncodeScale', // x001910f2: 'FastPhases', // x001910f9: 'TransmissionGain', x00200000: 'RelationshipGroupLength', x0020000d: 'StudyInstanceUID', x0020000e: 'SeriesInstanceUID', x00200010: 'StudyID', x00200011: 'SeriesNumber', x00200012: 'AcquisitionNumber', x00200013: 'InstanceNumber', x00200014: 'IsotopeNumber', x00200015: 'PhaseNumber', x00200016: 'IntervalNumber', x00200017: 'TimeSlotNumber', x00200018: 'AngleNumber', x00200019: 'ItemNumber', x00200020: 'PatientOrientation', x00200022: 'OverlayNumber', x00200024: 'CurveNumber', x00200026: 'LookupTableNumber', x00200030: 'ImagePosition', x00200032: 'ImagePositionPatient', x00200035: 'ImageOrientation', x00200037: 'ImageOrientationPatient', x00200050: 'Location', x00200052: 'FrameOfReferenceUID', x00200060: 'Laterality', x00200062: 'ImageLaterality', x00200070: 'ImageGeometryType', x00200080: 'MaskingImage', x00200100: 'TemporalPositionIdentifier', x00200105: 'NumberOfTemporalPositions', x00200110: 'TemporalResolution', x00200200: 'SynchronizationFrameOfReferenceUID', x00201000: 'SeriesInStudy', x00201001: 'AcquisitionsInSeries', x00201002: 'ImagesInAcquisition', x00201003: 'ImagesInSeries', x00201004: 'AcquisitionsInStudy', x00201005: 'ImagesInStudy', x00201020: 'Reference', x00201040: 'PositionReferenceIndicator', x00201041: 'SliceLocation', x00201070: 'OtherStudyNumbers', x00201200: 'NumberOfPatientRelatedStudies', x00201202: 'NumberOfPatientRelatedSeries', x00201204: 'NumberOfPatientRelatedInstances', x00201206: 'NumberOfStudyRelatedSeries', x00201208: 'NumberOfStudyRelatedInstances', x00201209: 'NumberOfSeriesRelatedInstances', x002031xx: 'SourceImageIDs', x00203401: 'ModifyingDeviceID', x00203402: 'ModifiedImageID', x00203403: 'ModifiedImageDate', x00203404: 'ModifyingDeviceManufacturer', x00203405: 'ModifiedImageTime', x00203406: 'ModifiedImageDescription', x00204000: 'ImageComments', x00205000: 'OriginalImageIdentification', x00205002: 'OriginalImageIdentNomenclature', x00209056: 'StackID', x00209057: 'InStackPositionNumber', x00209071: 'FrameAnatomySequence', x00209072: 'FrameLaterality', x00209111: 'FrameContentSequence', x00209113: 'PlanePositionSequence', x00209116: 'PlaneOrientationSequence', x00209128: 'TemporalPositionIndex', x00209153: 'TriggerDelayTime', x00209156: 'FrameAcquisitionNumber', x00209157: 'DimensionIndexValues', x00209158: 'FrameComments', x00209161: 'ConcatenationUID', x00209162: 'InConcatenationNumber', x00209163: 'InConcatenationTotalNumber', x00209164: 'DimensionOrganizationUID', x00209165: 'DimensionIndexPointer', x00209167: 'FunctionalGroupPointer', x00209213: 'DimensionIndexPrivateCreator', x00209221: 'DimensionOrganizationSequence', x00209222: 'DimensionIndexSequence', x00209228: 'ConcatenationFrameOffsetNumber', x00209238: 'FunctionalGroupPrivateCreator', x00209241: 'NominalPercentageOfCardiacPhase', x00209245: 'NominalPercentOfRespiratoryPhase', x00209246: 'StartingRespiratoryAmplitude', x00209247: 'StartingRespiratoryPhase', x00209248: 'EndingRespiratoryAmplitude', x00209249: 'EndingRespiratoryPhase', x00209250: 'RespiratoryTriggerType', x00209251: 'RRIntervalTimeNominal', x00209252: 'ActualCardiacTriggerDelayTime', x00209253: 'RespiratorySynchronizationSequence', x00209254: 'RespiratoryIntervalTime', x00209255: 'NominalRespiratoryTriggerDelayTime', x00209256: 'RespiratoryTriggerDelayThreshold', x00209257: 'ActualRespiratoryTriggerDelayTime', x00209301: 'ImagePositionVolume', x00209302: 'ImageOrientationVolume', x00209308: 'ApexPosition', x00209421: 'DimensionDescriptionLabel', x00209450: 'PatientOrientationInFrameSequence', x00209453: 'FrameLabel', x00209518: 'AcquisitionIndex', x00209529: 'ContributingSOPInstancesRefSeq', x00209536: 'ReconstructionIndex', // x00211003: 'SeriesFromWhichPrescribed', // x00211005: 'GenesisVersionNow', // x00211007: 'SeriesRecordChecksum', // x00211018: 'GenesisVersionNow', // x00211019: 'AcqreconRecordChecksum', // x00211020: 'TableStartLocation', // x00211035: 'SeriesFromWhichPrescribed', // x00211036: 'ImageFromWhichPrescribed', // x00211037: 'ScreenFormat', // x0021104a: 'AnatomicalReferenceForScout', // x0021104f: 'LocationsInAcquisition', // x00211050: 'GraphicallyPrescribed', // x00211051: 'RotationFromSourceXRot', // x00211052: 'RotationFromSourceYRot', // x00211053: 'RotationFromSourceZRot', // x00211054: 'ImagePosition', // x00211055: 'ImageOrientation', // x00211056: 'IntegerSlop', // x00211057: 'IntegerSlop', // x00211058: 'IntegerSlop', // x00211059: 'IntegerSlop', // x0021105a: 'IntegerSlop', // x0021105b: 'FloatSlop', // x0021105c: 'FloatSlop', // x0021105d: 'FloatSlop', // x0021105e: 'FloatSlop', // x0021105f: 'FloatSlop', // x00211081: 'AutoWindowLevelAlpha', // x00211082: 'AutoWindowLevelBeta', // x00211083: 'AutoWindowLevelWindow', // x00211084: 'ToWindowLevelLevel', // x00211090: 'TubeFocalSpotPosition', // x00211091: 'BiopsyPosition', // x00211092: 'BiopsyTLocation', // x00211093: 'BiopsyRefLocation', x00220001: 'LightPathFilterPassThroughWavelen', x00220002: 'LightPathFilterPassBand', x00220003: 'ImagePathFilterPassThroughWavelen', x00220004: 'ImagePathFilterPassBand', x00220005: 'PatientEyeMovementCommanded', x00220006: 'PatientEyeMovementCommandCodeSeq', x00220007: 'SphericalLensPower', x00220008: 'CylinderLensPower', x00220009: 'CylinderAxis', x0022000a: 'EmmetropicMagnification', x0022000b: 'IntraOcularPressure', x0022000c: 'HorizontalFieldOfView', x0022000d: 'PupilDilated', x0022000e: 'DegreeOfDilation', x00220010: 'StereoBaselineAngle', x00220011: 'StereoBaselineDisplacement', x00220012: 'StereoHorizontalPixelOffset', x00220013: 'StereoVerticalPixelOffset', x00220014: 'StereoRotation', x00220015: 'AcquisitionDeviceTypeCodeSequence', x00220016: 'IlluminationTypeCodeSequence', x00220017: 'LightPathFilterTypeStackCodeSeq', x00220018: 'ImagePathFilterTypeStackCodeSeq', x00220019: 'LensesCodeSequence', x0022001a: 'ChannelDescriptionCodeSequence', x0022001b: 'RefractiveStateSequence', x0022001c: 'MydriaticAgentCodeSequence', x0022001d: 'RelativeImagePositionCodeSequence', x00220020: 'StereoPairsSequence', x00220021: 'LeftImageSequence', x00220022: 'RightImageSequence', x00220030: 'AxialLengthOfTheEye', x00220031: 'OphthalmicFrameLocationSequence', x00220032: 'ReferenceCoordinates', x00220035: 'DepthSpatialResolution', x00220036: 'MaximumDepthDistortion', x00220037: 'AlongScanSpatialResolution', x00220038: 'MaximumAlongScanDistortion', x00220039: 'OphthalmicImageOrientation', x00220041: 'DepthOfTransverseImage', x00220042: 'MydriaticAgentConcUnitsSeq', x00220048: 'AcrossScanSpatialResolution', x00220049: 'MaximumAcrossScanDistortion', x0022004e: 'MydriaticAgentConcentration', x00220055: 'IlluminationWaveLength', x00220056: 'IlluminationPower', x00220057: 'IlluminationBandwidth', x00220058: 'MydriaticAgentSequence', // x00231001: 'NumberOfSeriesInStudy', // x00231002: 'NumberOfUnarchivedSeries', // x00231010: 'ReferenceImageField', // x00231050: 'SummaryImage', // x00231070: 'StartTimeSecsInFirstAxial', // x00231074: 'NoofUpdatesToHeader', // x0023107d: 'IndicatesIfTheStudyHasCompleteInfo', // x00251006: 'LastPulseSequenceUsed', // x00251007: 'ImagesInSeries', // x00251010: 'LandmarkCounter', // x00251011: 'NumberOfAcquisitions', // x00251014: 'IndicatesNoofUpdatesToHeader', // x00251017: 'SeriesCompleteFlag', // x00251018: 'NumberOfImagesArchived', // x00251019: 'LastImageNumberUsed', // x0025101a: 'PrimaryReceiverSuiteAndHost', // x00271006: 'ImageArchiveFlag', // x00271010: 'ScoutType', // x0027101c: 'VmaMamp', // x0027101d: 'VmaPhase', // x0027101e: 'VmaMod', // x0027101f: 'VmaClip', // x00271020: 'SmartScanOnOffFlag', // x00271030: 'ForeignImageRevision', // x00271031: 'ImagingMode', // x00271032: 'PulseSequence', // x00271033: 'ImagingOptions', // x00271035: 'PlaneType', // x00271036: 'ObliquePlane', // x00271040: 'RASLetterOfImageLocation', // x00271041: 'ImageLocation', // x00271042: 'CenterRCoordOfPlaneImage', // x00271043: 'CenterACoordOfPlaneImage', // x00271044: 'CenterSCoordOfPlaneImage', // x00271045: 'NormalRCoord', // x00271046: 'NormalACoord', // x00271047: 'NormalSCoord', // x00271048: 'RCoordOfTopRightCorner', // x00271049: 'ACoordOfTopRightCorner', // x0027104a: 'SCoordOfTopRightCorner', // x0027104b: 'RCoordOfBottomRightCorner', // x0027104c: 'ACoordOfBottomRightCorner', // x0027104d: 'SCoordOfBottomRightCorner', // x00271050: 'TableStartLocation', // x00271051: 'TableEndLocation', // x00271052: 'RASLetterForSideOfImage', // x00271053: 'RASLetterForAnteriorPosterior', // x00271054: 'RASLetterForScoutStartLoc', // x00271055: 'RASLetterForScoutEndLoc', // x00271060: 'ImageDimensionX', // x00271061: 'ImageDimensionY', // x00271062: 'NumberOfExcitations', x00280000: 'ImagePresentationGroupLength', x00280002: 'SamplesPerPixel', x00280003: 'SamplesPerPixelUsed', x00280004: 'PhotometricInterpretation', x00280005: 'ImageDimensions', x00280006: 'PlanarConfiguration', x00280008: 'NumberOfFrames', x00280009: 'FrameIncrementPointer', x0028000a: 'FrameDimensionPointer', x00280010: 'Rows', x00280011: 'Columns', x00280012: 'Planes', x00280014: 'UltrasoundColorDataPresent', x00280030: 'PixelSpacing', x00280031: 'ZoomFactor', x00280032: 'ZoomCenter', x00280034: 'PixelAspectRatio', x00280040: 'ImageFormat', x00280050: 'ManipulatedImage', x00280051: 'CorrectedImage', x0028005f: 'CompressionRecognitionCode', x00280060: 'CompressionCode', x00280061: 'CompressionOriginator', x00280062: 'CompressionLabel', x00280063: 'CompressionDescription', x00280065: 'CompressionSequence', x00280066: 'CompressionStepPointers', x00280068: 'RepeatInterval', x00280069: 'BitsGrouped', x00280070: 'PerimeterTable', x00280071: 'PerimeterValue', x00280080: 'PredictorRows', x00280081: 'PredictorColumns', x00280082: 'PredictorConstants', x00280090: 'BlockedPixels', x00280091: 'BlockRows', x00280092: 'BlockColumns', x00280093: 'RowOverlap', x00280094: 'ColumnOverlap', x00280100: 'BitsAllocated', x00280101: 'BitsStored', x00280102: 'HighBit', x00280103: 'PixelRepresentation', x00280104: 'SmallestValidPixelValue', x00280105: 'LargestValidPixelValue', x00280106: 'SmallestImagePixelValue', x00280107: 'LargestImagePixelValue', x00280108: 'SmallestPixelValueInSeries', x00280109: 'LargestPixelValueInSeries', x00280110: 'SmallestImagePixelValueInPlane', x00280111: 'LargestImagePixelValueInPlane', x00280120: 'PixelPaddingValue', x00280121: 'PixelPaddingRangeLimit', x00280200: 'ImageLocation', x00280300: 'QualityControlImage', x00280301: 'BurnedInAnnotation', x00280400: 'TransformLabel', x00280401: 'TransformVersionNumber', x00280402: 'NumberOfTransformSteps', x00280403: 'SequenceOfCompressedData', x00280404: 'DetailsOfCoefficients', x002804x2: 'CoefficientCoding', x002804x3: 'CoefficientCodingPointers', x00280700: 'DCTLabel', x00280701: 'DataBlockDescription', x00280702: 'DataBlock', x00280710: 'NormalizationFactorFormat', x00280720: 'ZonalMapNumberFormat', x00280721: 'ZonalMapLocation', x00280722: 'ZonalMapFormat', x00280730: 'AdaptiveMapFormat', x00280740: 'CodeNumberFormat', x002808x0: 'CodeLabel', x002808x2: 'NumberOfTables', x002808x3: 'CodeTableLocation', x002808x4: 'BitsForCodeWord', x002808x8: 'ImageDataLocation', x00280a02: 'PixelSpacingCalibrationType', x00280a04: 'PixelSpacingCalibrationDescription', x00281040: 'PixelIntensityRelationship', x00281041: 'PixelIntensityRelationshipSign', x00281050: 'WindowCenter', x00281051: 'WindowWidth', x00281052: 'RescaleIntercept', x00281053: 'RescaleSlope', x00281054: 'RescaleType', x00281055: 'WindowCenterAndWidthExplanation', x00281056: 'VOI_LUTFunction', x00281080: 'GrayScale', x00281090: 'RecommendedViewingMode', x00281100: 'GrayLookupTableDescriptor', x00281101: 'RedPaletteColorTableDescriptor', x00281102: 'GreenPaletteColorTableDescriptor', x00281103: 'BluePaletteColorTableDescriptor', x00281111: 'LargeRedPaletteColorTableDescr', x00281112: 'LargeGreenPaletteColorTableDescr', x00281113: 'LargeBluePaletteColorTableDescr', x00281199: 'PaletteColorTableUID', x00281200: 'GrayLookupTableData', x00281201: 'RedPaletteColorTableData', x00281202: 'GreenPaletteColorTableData', x00281203: 'BluePaletteColorTableData', x00281211: 'LargeRedPaletteColorTableData', x00281212: 'LargeGreenPaletteColorTableData', x00281213: 'LargeBluePaletteColorTableData', x00281214: 'LargePaletteColorLookupTableUID', x00281221: 'SegmentedRedColorTableData', x00281222: 'SegmentedGreenColorTableData', x00281223: 'SegmentedBlueColorTableData', x00281300: 'BreastImplantPresent', x00281350: 'PartialView', x00281351: 'PartialViewDescription', x00281352: 'PartialViewCodeSequence', x0028135a: 'SpatialLocationsPreserved', x00281402: 'DataPathAssignment', x00281404: 'BlendingLUT1Sequence', x00281406: 'BlendingWeightConstant', x00281408: 'BlendingLookupTableData', x0028140c: 'BlendingLUT2Sequence', x0028140e: 'DataPathID', x0028140f: 'RGBLUTTransferFunction', x00281410: 'AlphaLUTTransferFunction', x00282000: 'ICCProfile', x00282110: 'LossyImageCompression', x00282112: 'LossyImageCompressionRatio', x00282114: 'LossyImageCompressionMethod', x00283000: 'ModalityLUTSequence', x00283002: 'LUTDescriptor', x00283003: 'LUTExplanation', x00283004: 'ModalityLUTType', x00283006: 'LUTData', x00283010: 'VOILUTSequence', x00283110: 'SoftcopyVOILUTSequence', x00284000: 'ImagePresentationComments', x00285000: 'BiPlaneAcquisitionSequence', x00286010: 'RepresentativeFrameNumber', x00286020: 'FrameNumbersOfInterest', x00286022: 'FrameOfInterestDescription', x00286023: 'FrameOfInterestType', x00286030: 'MaskPointers', x00286040: 'RWavePointer', x00286100: 'MaskSubtractionSequence', x00286101: 'MaskOperation', x00286102: 'ApplicableFrameRange', x00286110: 'MaskFrameNumbers', x00286112: 'ContrastFrameAveraging', x00286114: 'MaskSubPixelShift', x00286120: 'TIDOffset', x00286190: 'MaskOperationExplanation', x00287fe0: 'PixelDataProviderURL', x00289001: 'DataPointRows', x00289002: 'DataPointColumns', x00289003: 'SignalDomainColumns', x00289099: 'LargestMonochromePixelValue', x00289108: 'DataRepresentation', x00289110: 'PixelMeasuresSequence', x00289132: 'FrameVOILUTSequence', x00289145: 'PixelValueTransformationSequence', x00289235: 'SignalDomainRows', x00289411: 'DisplayFilterPercentage', x00289415: 'FramePixelShiftSequence', x00289416: 'SubtractionItemID', x00289422: 'PixelIntensityRelationshipLUTSeq', x00289443: 'FramePixelDataPropertiesSequence', x00289444: 'GeometricalProperties', x00289445: 'GeometricMaximumDistortion', x00289446: 'ImageProcessingApplied', x00289454: 'MaskSelectionMode', x00289474: 'LUTFunction', x00289478: 'MaskVisibilityPercentage', x00289501: 'PixelShiftSequence', x00289502: 'RegionPixelShiftSequence', x00289503: 'VerticesOfTheRegion', x00289506: 'PixelShiftFrameRange', x00289507: 'LUTFrameRange', x00289520: 'ImageToEquipmentMappingMatrix', x00289537: 'EquipmentCoordinateSystemID', // x00291004: 'LowerRangeOfPixels1a', // x00291005: 'LowerRangeOfPixels1b', // x00291006: 'LowerRangeOfPixels1c', // x00291007: 'LowerRangeOfPixels1d', // x00291008: 'LowerRangeOfPixels1e', // x00291009: 'LowerRangeOfPixels1f', // x0029100a: 'LowerRangeOfPixels1g', // x00291015: 'LowerRangeOfPixels1h', // x00291016: 'LowerRangeOfPixels1i', // x00291017: 'LowerRangeOfPixels2', // x00291018: 'UpperRangeOfPixels2', // x0029101a: 'LenOfTotHdrInBytes', // x00291026: 'VersionOfTheHdrStruct', // x00291034: 'AdvantageCompOverflow', // x00291035: 'AdvantageCompUnderflow', x00320000: 'StudyGroupLength', x0032000a: 'StudyStatusID', x0032000c: 'StudyPriorityID', x00320012: 'StudyIDIssuer', x00320032: 'StudyVerifiedDate', x00320033: 'StudyVerifiedTime', x00320034: 'StudyReadDate', x00320035: 'StudyReadTime', x00321000: 'ScheduledStudyStartDate', x00321001: 'ScheduledStudyStartTime', x00321010: 'ScheduledStudyStopDate', x00321011: 'ScheduledStudyStopTime', x00321020: 'ScheduledStudyLocation', x00321021: 'ScheduledStudyLocationAETitle', x00321030: 'ReasonForStudy', x00321031: 'RequestingPhysicianIDSequence', x00321032: 'RequestingPhysician', x00321033: 'RequestingService', x00321040: 'StudyArrivalDate', x00321041: 'StudyArrivalTime', x00321050: 'StudyCompletionDate', x00321051: 'StudyCompletionTime', x00321055: 'StudyComponentStatusID', x00321060: 'RequestedProcedureDescription', x00321064: 'RequestedProcedureCodeSequence', x00321070: 'RequestedContrastAgent', x00324000: 'StudyComments', x00380004: 'ReferencedPatientAliasSequence', x00380008: 'VisitStatusID', x00380010: 'AdmissionID', x00380011: 'IssuerOfAdmissionID', x00380016: 'RouteOfAdmissions', x0038001a: 'ScheduledAdmissionDate', x0038001b: 'ScheduledAdmissionTime', x0038001c: 'ScheduledDischargeDate', x0038001d: 'ScheduledDischargeTime', x0038001e: 'ScheduledPatientInstitResidence', x00380020: 'AdmittingDate', x00380021: 'AdmittingTime', x00380030: 'DischargeDate', x00380032: 'DischargeTime', x00380040: 'DischargeDiagnosisDescription', x00380044: 'DischargeDiagnosisCodeSequence', x00380050: 'SpecialNeeds', x00380060: 'ServiceEpisodeID', x00380061: 'IssuerOfServiceEpisodeID', x00380062: 'ServiceEpisodeDescription', x00380100: 'PertinentDocumentsSequence', x00380300: 'CurrentPatientLocation', x00380400: 'PatientInstitutionResidence', x00380500: 'PatientState', x00380502: 'PatientClinicalTrialParticipSeq', x00384000: 'VisitComments', x003a0004: 'WaveformOriginality', x003a0005: 'NumberOfWaveformChannels', x003a0010: 'NumberOfWaveformSamples', x003a001a: 'SamplingFrequency', x003a0020: 'MultiplexGroupLabel', x003a0200: 'ChannelDefinitionSequence', x003a0202: 'WaveformChannelNumber', x003a0203: 'ChannelLabel', x003a0205: 'ChannelStatus', x003a0208: 'ChannelSourceSequence', x003a0209: 'ChannelSourceModifiersSequence', x003a020a: 'SourceWaveformSequence', x003a020c: 'ChannelDerivationDescription', x003a0210: 'ChannelSensitivity', x003a0211: 'ChannelSensitivityUnitsSequence', x003a0212: 'ChannelSensitivityCorrectionFactor', x003a0213: 'ChannelBaseline', x003a0214: 'ChannelTimeSkew', x003a0215: 'ChannelSampleSkew', x003a0218: 'ChannelOffset', x003a021a: 'WaveformBitsStored', x003a0220: 'FilterLowFrequency', x003a0221: 'FilterHighFrequency', x003a0222: 'NotchFilterFrequency', x003a0223: 'NotchFilterBandwidth', x003a0230: 'WaveformDataDisplayScale', x003a0231: 'WaveformDisplayBkgCIELabValue', x003a0240: 'WaveformPresentationGroupSequence', x003a0241: 'PresentationGroupNumber', x003a0242: 'ChannelDisplaySequence', x003a0244: 'ChannelRecommendDisplayCIELabValue', x003a0245: 'ChannelPosition', x003a0246: 'DisplayShadingFlag', x003a0247: 'FractionalChannelDisplayScale', x003a0248: 'AbsoluteChannelDisplayScale', x003a0300: 'MultiplexAudioChannelsDescrCodeSeq', x003a0301: 'ChannelIdentificationCode', x003a0302: 'ChannelMode', x00400001: 'ScheduledStationAETitle', x00400002: 'ScheduledProcedureStepStartDate', x00400003: 'ScheduledProcedureStepStartTime', x00400004: 'ScheduledProcedureStepEndDate', x00400005: 'ScheduledProcedureStepEndTime', x00400006: 'ScheduledPerformingPhysiciansName', x00400007: 'ScheduledProcedureStepDescription', x00400008: 'ScheduledProtocolCodeSequence', x00400009: 'ScheduledProcedureStepID', x0040000a: 'StageCodeSequence', x0040000b: 'ScheduledPerformingPhysicianIDSeq', x00400010: 'ScheduledStationName', x00400011: 'ScheduledProcedureStepLocation', x00400012: 'PreMedication', x00400020: 'ScheduledProcedureStepStatus', x00400031: 'LocalNamespaceEntityID', x00400032: 'UniversalEntityID', x00400033: 'UniversalEntityIDType', x00400035: 'IdentifierTypeCode', x00400036: 'AssigningFacilitySequence', x00400100: 'ScheduledProcedureStepSequence', x00400220: 'ReferencedNonImageCompositeSOPSeq', x00400241: 'PerformedStationAETitle', x00400242: 'PerformedStationName', x00400243: 'PerformedLocation', x00400244: 'PerformedProcedureStepStartDate', x00400245: 'PerformedProcedureStepStartTime', x00400250: 'PerformedProcedureStepEndDate', x00400251: 'PerformedProcedureStepEndTime', x00400252: 'PerformedProcedureStepStatus', x00400253: 'PerformedProcedureStepID', x00400254: 'PerformedProcedureStepDescription', x00400255: 'PerformedProcedureTypeDescription', x00400260: 'PerformedProtocolCodeSequence', x00400261: 'PerformedProtocolType', x00400270: 'ScheduledStepAttributesSequence', x00400275: 'RequestAttributesSequence', x00400280: 'CommentsOnPerformedProcedureStep', x00400281: 'ProcStepDiscontinueReasonCodeSeq', x00400293: 'QuantitySequence', x00400294: 'Quantity', x00400295: 'MeasuringUnitsSequence', x00400296: 'BillingItemSequence', x00400300: 'TotalTimeOfFluoroscopy', x00400301: 'TotalNumberOfExposures', x00400302: 'EntranceDose', x00400303: 'ExposedArea', x00400306: 'DistanceSourceToEntrance', x00400307: 'DistanceSourceToSupport', x0040030e: 'ExposureDoseSequence', x00400310: 'CommentsOnRadiationDose', x00400312: 'XRayOutput', x00400314: 'HalfValueLayer', x00400316: 'OrganDose', x00400318: 'OrganExposed', x00400320: 'BillingProcedureStepSequence', x00400321: 'FilmConsumptionSequence', x00400324: 'BillingSuppliesAndDevicesSequence', x00400330: 'ReferencedProcedureStepSequence', x00400340: 'PerformedSeriesSequence', x00400400: 'CommentsOnScheduledProcedureStep', x00400440: 'ProtocolContextSequence', x00400441: 'ContentItemModifierSequence', x0040050a: 'SpecimenAccessionNumber', x00400512: 'ContainerIdentifier', x0040051a: 'ContainerDescription', x00400550: 'SpecimenSequence', x00400551: 'SpecimenIdentifier', x00400552: 'SpecimenDescriptionSequenceTrial', x00400553: 'SpecimenDescriptionTrial', x00400554: 'SpecimenUID', x00400555: 'AcquisitionContextSequence', x00400556: 'AcquisitionContextDescription', x0040059a: 'SpecimenTypeCodeSequence', x00400600: 'SpecimenShortDescription', x004006fa: 'SlideIdentifier', x0040071a: 'ImageCenterPointCoordinatesSeq', x0040072a: 'XOffsetInSlideCoordinateSystem', x0040073a: 'YOffsetInSlideCoordinateSystem', x0040074a: 'ZOffsetInSlideCoordinateSystem', x004008d8: 'PixelSpacingSequence', x004008da: 'CoordinateSystemAxisCodeSequence', x004008ea: 'MeasurementUnitsCodeSequence', x004009f8: 'VitalStainCodeSequenceTrial', x00401001: 'RequestedProcedureID', x00401002: 'ReasonForRequestedProcedure', x00401003: 'RequestedProcedurePriority', x00401004: 'PatientTransportArrangements', x00401005: 'RequestedProcedureLocation', x00401006: 'PlacerOrderNumber-Procedure', x00401007: 'FillerOrderNumber-Procedure', x00401008: 'ConfidentialityCode', x00401009: 'ReportingPriority', x0040100a: 'ReasonForRequestedProcedureCodeSeq', x00401010: 'NamesOfIntendedRecipientsOfResults', x00401011: 'IntendedRecipientsOfResultsIDSeq', x00401101: 'PersonIdentificationCodeSequence', x00401102: 'PersonAddress', x00401103: 'PersonTelephoneNumbers', x00401400: 'RequestedProcedureComments', x00402001: 'ReasonForImagingServiceRequest', x00402004: 'IssueDateOfImagingServiceRequest', x00402005: 'IssueTimeOfImagingServiceRequest', x00402006: 'PlacerOrderNumberImagingServiceRequestRetired', x00402007: 'FillerOrderNumberImagingServiceRequestRetired', x00402008: 'OrderEnteredBy', x00402009: 'OrderEntererLocation', x00402010: 'OrderCallbackPhoneNumber', x00402016: 'PlacerOrderNum-ImagingServiceReq', x00402017: 'FillerOrderNum-ImagingServiceReq', x00402400: 'ImagingServiceRequestComments', x00403001: 'ConfidentialityOnPatientDataDescr', x00404001: 'GenPurposeScheduledProcStepStatus', x00404002: 'GenPurposePerformedProcStepStatus', x00404003: 'GenPurposeSchedProcStepPriority', x00404004: 'SchedProcessingApplicationsCodeSeq', x00404005: 'SchedProcedureStepStartDateAndTime', x00404006: 'MultipleCopiesFlag', x00404007: 'PerformedProcessingAppsCodeSeq', x00404009: 'HumanPerformerCodeSequence', x00404010: 'SchedProcStepModificationDateTime', x00404011: 'ExpectedCompletionDateAndTime', x00404015: 'ResultingGenPurposePerfProcStepSeq', x00404016: 'RefGenPurposeSchedProcStepSeq', x00404018: 'ScheduledWorkitemCodeSequence', x00404019: 'PerformedWorkitemCodeSequence', x00404020: 'InputAvailabilityFlag', x00404021: 'InputInformationSequence', x00404022: 'RelevantInformationSequence', x00404023: 'RefGenPurSchedProcStepTransUID', x00404025: 'ScheduledStationNameCodeSequence', x00404026: 'ScheduledStationClassCodeSequence', x00404027: 'SchedStationGeographicLocCodeSeq', x00404028: 'PerformedStationNameCodeSequence', x00404029: 'PerformedStationClassCodeSequence', x00404030: 'PerformedStationGeogLocCodeSeq', x00404031: 'RequestedSubsequentWorkItemCodeSeq', x00404032: 'NonDICOMOutputCodeSequence', x00404033: 'OutputInformationSequence', x00404034: 'ScheduledHumanPerformersSequence', x00404035: 'ActualHumanPerformersSequence', x00404036: 'HumanPerformersOrganization', x00404037: 'HumanPerformerName', x00404040: 'RawDataHandling', x00408302: 'EntranceDoseInMilliGy', x00409094: 'RefImageRealWorldValueMappingSeq', x00409096: 'RealWorldValueMappingSequence', x00409098: 'PixelValueMappingCodeSequence', x00409210: 'LUTLabel', x00409211: 'RealWorldValueLastValueMapped', x00409212: 'RealWorldValueLUTData', x00409216: 'RealWorldValueFirstValueMapped', x00409224: 'RealWorldValueIntercept', x00409225: 'RealWorldValueSlope', x0040a010: 'RelationshipType', x0040a027: 'VerifyingOrganization', x0040a030: 'VerificationDateTime', x0040a032: 'ObservationDateTime', x0040a040: 'ValueType', x0040a043: 'ConceptNameCodeSequence', x0040a050: 'ContinuityOfContent', x0040a073: 'VerifyingObserverSequence', x0040a075: 'VerifyingObserverName', x0040a078: 'AuthorObserverSequence', x0040a07a: 'ParticipantSequence', x0040a07c: 'CustodialOrganizationSequence', x0040a080: 'ParticipationType', x0040a082: 'ParticipationDateTime', x0040a084: 'ObserverType', x0040a088: 'VerifyingObserverIdentCodeSequence', x0040a090: 'EquivalentCDADocumentSequence', x0040a0b0: 'ReferencedWaveformChannels', x0040a120: 'DateTime', x0040a121: 'Date', x0040a122: 'Time', x0040a123: 'PersonName', x0040a124: 'UID', x0040a130: 'TemporalRangeType', x0040a132: 'ReferencedSamplePositions', x0040a136: 'ReferencedFrameNumbers', x0040a138: 'ReferencedTimeOffsets', x0040a13a: 'ReferencedDateTime', x0040a160: 'TextValue', x0040a168: 'ConceptCodeSequence', x0040a170: 'PurposeOfReferenceCodeSequence', x0040a180: 'AnnotationGroupNumber', x0040a195: 'ModifierCodeSequence', x0040a300: 'MeasuredValueSequence', x0040a301: 'NumericValueQualifierCodeSequence', x0040a30a: 'NumericValue', x0040a353: 'AddressTrial', x0040a354: 'TelephoneNumberTrial', x0040a360: 'PredecessorDocumentsSequence', x0040a370: 'ReferencedRequestSequence', x0040a372: 'PerformedProcedureCodeSequence', x0040a375: 'CurrentRequestedProcEvidenceSeq', x0040a385: 'PertinentOtherEvidenceSequence', x0040a390: 'HL7StructuredDocumentRefSeq', x0040a491: 'CompletionFlag', x0040a492: 'CompletionFlagDescription', x0040a493: 'VerificationFlag', x0040a494: 'ArchiveRequested', x0040a496: 'PreliminaryFlag', x0040a504: 'ContentTemplateSequence', x0040a525: 'IdenticalDocumentsSequence', x0040a730: 'ContentSequence', x0040b020: 'AnnotationSequence', x0040db00: 'TemplateIdentifier', x0040db06: 'TemplateVersion', x0040db07: 'TemplateLocalVersion', x0040db0b: 'TemplateExtensionFlag', x0040db0c: 'TemplateExtensionOrganizationUID', x0040db0d: 'TemplateExtensionCreatorUID', x0040db73: 'ReferencedContentItemIdentifier', x0040e001: 'HL7InstanceIdentifier', x0040e004: 'HL7DocumentEffectiveTime', x0040e006: 'HL7DocumentTypeCodeSequence', x0040e010: 'RetrieveURI', x0040e011: 'RetrieveLocationUID', x00420010: 'DocumentTitle', x00420011: 'EncapsulatedDocument', x00420012: 'MIMETypeOfEncapsulatedDocument', x00420013: 'SourceInstanceSequence', x00420014: 'ListOfMIMETypes', // x00431001: 'BitmapOfPrescanOptions', // x00431002: 'GradientOffsetInX', // x00431003: 'GradientOffsetInY', // x00431004: 'GradientOffsetInZ', // x00431005: 'ImgIsOriginalOrUnoriginal', // x00431006: 'NumberOfEPIShots', // x00431007: 'ViewsPerSegment', // x00431008: 'RespiratoryRateBpm', // x00431009: 'RespiratoryTriggerPoint', // x0043100a: 'TypeOfReceiverUsed', // x0043100b: 'PeakRateOfChangeOfGradientField', // x0043100c: 'LimitsInUnitsOfPercent', // x0043100d: 'PSDEstimatedLimit', // x0043100e: 'PSDEstimatedLimitInTeslaPerSecond', // x0043100f: 'Saravghead', // x00431010: 'WindowValue', // x00431011: 'TotalInputViews', // x00431012: 'X-RayChain', // x00431013: 'DeconKernelParameters', // x00431014: 'CalibrationParameters', // x00431015: 'TotalOutputViews', // x00431016: 'NumberOfOverranges', // x00431017: 'IBHImageScaleFactors', // x00431018: 'BBHCoefficients', // x00431019: 'NumberOfBBHChainsToBlend', // x0043101a: 'StartingChannelNumber', // x0043101b: 'PpscanParameters', // x0043101c: 'GEImageIntegrity', // x0043101d: 'LevelValue', // x0043101e: 'DeltaStartTime', // x0043101f: 'MaxOverrangesInAView', // x00431020: 'AvgOverrangesAllViews', // x00431021: 'CorrectedAfterGlowTerms', // x00431025: 'ReferenceChannels', // x00431026: 'NoViewsRefChansBlocked', // x00431027: 'ScanPitchRatio', // x00431028: 'UniqueImageIden', // x00431029: 'HistogramTables', // x0043102a: 'UserDefinedData', // x0043102b: 'PrivateScanOptions', // x0043102c: 'EffectiveEchoSpacing', // x0043102d: 'StringSlopField1', // x0043102e: 'StringSlopField2', // x0043102f: 'RawDataType', // x00431030: 'RawDataType', // x00431031: 'RACordOfTargetReconCenter', // x00431032: 'RawDataType', // x00431033: 'NegScanspacing', // x00431034: 'OffsetFrequency', // x00431035: 'UserUsageTag', // x00431036: 'UserFillMapMSW', // x00431037: 'UserFillMapLSW', // x00431038: 'User25-48', // x00431039: 'SlopInt6-9', // x00431040: 'TriggerOnPosition', // x00431041: 'DegreeOfRotation', // x00431042: 'DASTriggerSource', // x00431043: 'DASFpaGain', // x00431044: 'DASOutputSource', // x00431045: 'DASAdInput', // x00431046: 'DASCalMode', // x00431047: 'DASCalFrequency', // x00431048: 'DASRegXm', // x00431049: 'DASAutoZero', // x0043104a: 'StartingChannelOfView', // x0043104b: 'DASXmPattern', // x0043104c: 'TGGCTriggerMode', // x0043104d: 'StartScanToXrayOnDelay', // x0043104e: 'DurationOfXrayOn', // x00431060: 'SlopInt10-17', // x00431061: 'ScannerStudyEntityUID', // x00431062: 'ScannerStudyID', // x0043106f: 'ScannerTableEntry', x00440001: 'ProductPackageIdentifier', x00440002: 'SubstanceAdministrationApproval', x00440003: 'ApprovalStatusFurtherDescription', x00440004: 'ApprovalStatusDateTime', x00440007: 'ProductTypeCodeSequence', x00440008: 'ProductName', x00440009: 'ProductDescription', x0044000a: 'ProductLotIdentifier', x0044000b: 'ProductExpirationDateTime', x00440010: 'SubstanceAdministrationDateTime', x00440011: 'SubstanceAdministrationNotes', x00440012: 'SubstanceAdministrationDeviceID', x00440013: 'ProductParameterSequence', x00440019: 'SubstanceAdminParameterSeq', // x00451001: 'NumberOfMacroRowsInDetector', // x00451002: 'MacroWidthAtISOCenter', // x00451003: 'DASType', // x00451004: 'DASGain', // x00451005: 'DASTemperature', // x00451006: 'TableDirectionInOrOut', // x00451007: 'ZSmoothingFactor', // x00451008: 'ViewWeightingMode', // x00451009: 'SigmaRowNumberWhichRowsWereUsed', // x0045100a: 'MinimumDasValueFoundInTheScanData', // x0045100b: 'MaximumOffsetShiftValueUsed', // x0045100c: 'NumberOfViewsShifted', // x0045100d: 'ZTrackingFlag', // x0045100e: 'MeanZError', // x0045100f: 'ZTrackingMaximumError', // x00451010: 'StartingViewForRow2a', // x00451011: 'NumberOfViewsInRow2a', // x00451012: 'StartingViewForRow1a', // x00451013: 'SigmaMode', // x00451014: 'NumberOfViewsInRow1a', // x00451015: 'StartingViewForRow2b', // x00451016: 'NumberOfViewsInRow2b', // x00451017: 'StartingViewForRow1b', // x00451018: 'NumberOfViewsInRow1b', // x00451019: 'AirFilterCalibrationDate', // x0045101a: 'AirFilterCalibrationTime', // x0045101b: 'PhantomCalibrationDate', // x0045101c: 'PhantomCalibrationTime', // x0045101d: 'ZSlopeCalibrationDate', // x0045101e: 'ZSlopeCalibrationTime', // x0045101f: 'CrosstalkCalibrationDate', // x00451020: 'CrosstalkCalibrationTime', // x00451021: 'IterboneOptionFlag', // x00451022: 'PeristalticFlagOption', x00460012: 'LensDescription', x00460014: 'RightLensSequence', x00460015: 'LeftLensSequence', x00460018: 'CylinderSequence', x00460028: 'PrismSequence', x00460030: 'HorizontalPrismPower', x00460032: 'HorizontalPrismBase', x00460034: 'VerticalPrismPower', x00460036: 'VerticalPrismBase', x00460038: 'LensSegmentType', x00460040: 'OpticalTransmittance', x00460042: 'ChannelWidth', x00460044: 'PupilSize', x00460046: 'CornealSize', x00460060: 'DistancePupillaryDistance', x00460062: 'NearPupillaryDistance', x00460064: 'OtherPupillaryDistance', x00460075: 'RadiusOfCurvature', x00460076: 'KeratometricPower', x00460077: 'KeratometricAxis', x00460092: 'BackgroundColor', x00460094: 'Optotype', x00460095: 'OptotypePresentation', x00460100: 'AddNearSequence', x00460101: 'AddIntermediateSequence', x00460102: 'AddOtherSequence', x00460104: 'AddPower', x00460106: 'ViewingDistance', x00460125: 'ViewingDistanceType', x00460135: 'VisualAcuityModifiers', x00460137: 'DecimalVisualAcuity', x00460139: 'OptotypeDetailedDefinition', x00460146: 'SpherePower', x00460147: 'CylinderPower', x00500004: 'CalibrationImage', x00500010: 'DeviceSequence', x00500014: 'DeviceLength', x00500015: 'ContainerComponentWidth', x00500016: 'DeviceDiameter', x00500017: 'DeviceDiameterUnits', x00500018: 'DeviceVolume', x00500019: 'InterMarkerDistance', x0050001b: 'ContainerComponentID', x00500020: 'DeviceDescription', x00540010: 'EnergyWindowVector', x00540011: 'NumberOfEnergyWindows', x00540012: 'EnergyWindowInformationSequence', x00540013: 'EnergyWindowRangeSequence', x00540014: 'EnergyWindowLowerLimit', x00540015: 'EnergyWindowUpperLimit', x00540016: 'RadiopharmaceuticalInformationSeq', x00540017: 'ResidualSyringeCounts', x00540018: 'EnergyWindowName', x00540020: 'DetectorVector', x00540021: 'NumberOfDetectors', x00540022: 'DetectorInformationSequence', x00540030: 'PhaseVector', x00540031: 'NumberOfPhases', x00540032: 'PhaseInformationSequence', x00540033: 'NumberOfFramesInPhase', x00540036: 'PhaseDelay', x00540038: 'PauseBetweenFrames', x00540039: 'PhaseDescription', x00540050: 'RotationVector', x00540051: 'NumberOfRotations', x00540052: 'RotationInformationSequence', x00540053: 'NumberOfFramesInRotation', x00540060: 'RRIntervalVector', x00540061: 'NumberOfRRIntervals', x00540062: 'GatedInformationSequence', x00540063: 'DataInformationSequence', x00540070: 'TimeSlotVector', x00540071: 'NumberOfTimeSlots', x00540072: 'TimeSlotInformationSequence', x00540073: 'TimeSlotTime', x00540080: 'SliceVector', x00540081: 'NumberOfSlices', x00540090: 'AngularViewVector', x00540100: 'TimeSliceVector', x00540101: 'NumberOfTimeSlices', x00540200: 'StartAngle', x00540202: 'TypeOfDetectorMotion', x00540210: 'TriggerVector', x00540211: 'NumberOfTriggersInPhase', x00540220: 'ViewCodeSequence', x00540222: 'ViewModifierCodeSequence', x00540300: 'RadionuclideCodeSequence', x00540302: 'AdministrationRouteCodeSequence', x00540304: 'RadiopharmaceuticalCodeSequence', x00540306: 'CalibrationDataSequence', x00540308: 'EnergyWindowNumber', x00540400: 'ImageID', x00540410: 'PatientOrientationCodeSequence', x00540412: 'PatientOrientationModifierCodeSeq', x00540414: 'PatientGantryRelationshipCodeSeq', x00540500: 'SliceProgressionDirection', x00541000: 'SeriesType', x00541001: 'Units', x00541002: 'CountsSource', x00541004: 'ReprojectionMethod', x00541100: 'RandomsCorrectionMethod', x00541101: 'AttenuationCorrectionMethod', x00541102: 'DecayCorrection', x00541103: 'ReconstructionMethod', x00541104: 'DetectorLinesOfResponseUsed', x00541105: 'ScatterCorrectionMethod', x00541200: 'AxialAcceptance', x00541201: 'AxialMash', x00541202: 'TransverseMash', x00541203: 'DetectorElementSize', x00541210: 'CoincidenceWindowWidth', x00541220: 'SecondaryCountsType', x00541300: 'FrameReferenceTime', x00541310: 'PrimaryCountsAccumulated', x00541311: 'SecondaryCountsAccumulated', x00541320: 'SliceSensitivityFactor', x00541321: 'DecayFactor', x00541322: 'DoseCalibrationFactor', x00541323: 'ScatterFractionFactor', x00541324: 'DeadTimeFactor', x00541330: 'ImageIndex', x00541400: 'CountsIncluded', x00541401: 'DeadTimeCorrectionFlag', x00603000: 'HistogramSequence', x00603002: 'HistogramNumberOfBins', x00603004: 'HistogramFirstBinValue', x00603006: 'HistogramLastBinValue', x00603008: 'HistogramBinWidth', x00603010: 'HistogramExplanation', x00603020: 'HistogramData', x00620001: 'SegmentationType', x00620002: 'SegmentSequence', x00620003: 'SegmentedPropertyCategoryCodeSeq', x00620004: 'SegmentNumber', x00620005: 'SegmentLabel', x00620006: 'SegmentDescription', x00620008: 'SegmentAlgorithmType', x00620009: 'SegmentAlgorithmName', x0062000a: 'SegmentIdentificationSequence', x0062000b: 'ReferencedSegmentNumber', x0062000c: 'RecommendedDisplayGrayscaleValue', x0062000d: 'RecommendedDisplayCIELabValue', x0062000e: 'MaximumFractionalValue', x0062000f: 'SegmentedPropertyTypeCodeSequence', x00620010: 'SegmentationFractionalType', x00640002: 'DeformableRegistrationSequence', x00640003: 'SourceFrameOfReferenceUID', x00640005: 'DeformableRegistrationGridSequence', x00640007: 'GridDimensions', x00640008: 'GridResolution', x00640009: 'VectorGridData', x0064000f: 'PreDeformationMatrixRegistSeq', x00640010: 'PostDeformationMatrixRegistSeq', x00660001: 'NumberOfSurfaces', x00660002: 'SurfaceSequence', x00660003: 'SurfaceNumber', x00660004: 'SurfaceComments', x00660009: 'SurfaceProcessing', x0066000a: 'SurfaceProcessingRatio', x0066000e: 'FiniteVolume', x00660010: 'Manifold', x00660011: 'SurfacePointsSequence', x00660015: 'NumberOfSurfacePoints', x00660016: 'PointCoordinatesData', x00660017: 'PointPositionAccuracy', x00660018: 'MeanPointDistance', x00660019: 'MaximumPointDistance', x0066001b: 'AxisOfRotation', x0066001c: 'CenterOfRotation', x0066001e: 'NumberOfVectors', x0066001f: 'VectorDimensionality', x00660020: 'VectorAccuracy', x00660021: 'VectorCoordinateData', x00660023: 'TrianglePointIndexList', x00660024: 'EdgePointIndexList', x00660025: 'VertexPointIndexList', x00660026: 'TriangleStripSequence', x00660027: 'TriangleFanSequence', x00660028: 'LineSequence', x00660029: 'PrimitivePointIndexList', x0066002a: 'SurfaceCount', x0066002f: 'AlgorithmFamilyCodeSequ', x00660031: 'AlgorithmVersion', x00660032: 'AlgorithmParameters', x00660034: 'FacetSequence', x00660036: 'AlgorithmName', x00700001: 'GraphicAnnotationSequence', x00700002: 'GraphicLayer', x00700003: 'BoundingBoxAnnotationUnits', x00700004: 'AnchorPointAnnotationUnits', x00700005: 'GraphicAnnotationUnits', x00700006: 'UnformattedTextValue', x00700008: 'TextObjectSequence', x00700009: 'GraphicObjectSequence', x00700010: 'BoundingBoxTopLeftHandCorner', x00700011: 'BoundingBoxBottomRightHandCorner', x00700012: 'BoundingBoxTextHorizJustification', x00700014: 'AnchorPoint', x00700015: 'AnchorPointVisibility', x00700020: 'GraphicDimensions', x00700021: 'NumberOfGraphicPoints', x00700022: 'GraphicData', x00700023: 'GraphicType', x00700024: 'GraphicFilled', x00700040: 'ImageRotationRetired', x00700041: 'ImageHorizontalFlip', x00700042: 'ImageRotation', x00700050: 'DisplayedAreaTopLeftTrial', x00700051: 'DisplayedAreaBottomRightTrial', x00700052: 'DisplayedAreaTopLeft', x00700053: 'DisplayedAreaBottomRight', x0070005a: 'DisplayedAreaSelectionSequence', x00700060: 'GraphicLayerSequence', x00700062: 'GraphicLayerOrder', x00700066: 'GraphicLayerRecDisplayGraysclValue', x00700067: 'GraphicLayerRecDisplayRGBValue', x00700068: 'GraphicLayerDescription', x00700080: 'ContentLabel', x00700081: 'ContentDescription', x00700082: 'PresentationCreationDate', x00700083: 'PresentationCreationTime', x00700084: 'ContentCreatorName', x00700086: 'ContentCreatorIDCodeSequence', x00700100: 'PresentationSizeMode', x00700101: 'PresentationPixelSpacing', x00700102: 'PresentationPixelAspectRatio', x00700103: 'PresentationPixelMagRatio', x00700306: 'ShapeType', x00700308: 'RegistrationSequence', x00700309: 'MatrixRegistrationSequence', x0070030a: 'MatrixSequence', x0070030c: 'FrameOfRefTransformationMatrixType', x0070030d: 'RegistrationTypeCodeSequence', x0070030f: 'FiducialDescription', x00700310: 'FiducialIdentifier', x00700311: 'FiducialIdentifierCodeSequence', x00700312: 'ContourUncertaintyRadius', x00700314: 'UsedFiducialsSequence', x00700318: 'GraphicCoordinatesDataSequence', x0070031a: 'FiducialUID', x0070031c: 'FiducialSetSequence', x0070031e: 'FiducialSequence', x00700401: 'GraphicLayerRecomDisplayCIELabVal', x00700402: 'BlendingSequence', x00700403: 'RelativeOpacity', x00700404: 'ReferencedSpatialRegistrationSeq', x00700405: 'BlendingPosition', x00720002: 'HangingProtocolName', x00720004: 'HangingProtocolDescription', x00720006: 'HangingProtocolLevel', x00720008: 'HangingProtocolCreator', x0072000a: 'HangingProtocolCreationDateTime', x0072000c: 'HangingProtocolDefinitionSequence', x0072000e: 'HangingProtocolUserIDCodeSequence', x00720010: 'HangingProtocolUserGroupName', x00720012: 'SourceHangingProtocolSequence', x00720014: 'NumberOfPriorsReferenced', x00720020: 'ImageSetsSequence', x00720022: 'ImageSetSelectorSequence', x00720024: 'ImageSetSelectorUsageFlag', x00720026: 'SelectorAttribute', x00720028: 'SelectorValueNumber', x00720030: 'TimeBasedImageSetsSequence', x00720032: 'ImageSetNumber', x00720034: 'ImageSetSelectorCategory', x00720038: 'RelativeTime', x0072003a: 'RelativeTimeUnits', x0072003c: 'AbstractPriorValue', x0072003e: 'AbstractPriorCodeSequence', x00720040: 'ImageSetLabel', x00720050: 'SelectorAttributeVR', x00720052: 'SelectorSequencePointer', x00720054: 'SelectorSeqPointerPrivateCreator', x00720056: 'SelectorAttributePrivateCreator', x00720060: 'SelectorATValue', x00720062: 'SelectorCSValue', x00720064: 'SelectorISValue', x00720066: 'SelectorLOValue', x00720068: 'SelectorLTValue', x0072006a: 'SelectorPNValue', x0072006c: 'SelectorSHValue', x0072006e: 'SelectorSTValue', x00720070: 'SelectorUTValue', x00720072: 'SelectorDSValue', x00720074: 'SelectorFDValue', x00720076: 'SelectorFLValue', x00720078: 'SelectorULValue', x0072007a: 'SelectorUSValue', x0072007c: 'SelectorSLValue', x0072007e: 'SelectorSSValue', x00720080: 'SelectorCodeSequenceValue', x00720100: 'NumberOfScreens', x00720102: 'NominalScreenDefinitionSequence', x00720104: 'NumberOfVerticalPixels', x00720106: 'NumberOfHorizontalPixels', x00720108: 'DisplayEnvironmentSpatialPosition', x0072010a: 'ScreenMinimumGrayscaleBitDepth', x0072010c: 'ScreenMinimumColorBitDepth', x0072010e: 'ApplicationMaximumRepaintTime', x00720200: 'DisplaySetsSequence', x00720202: 'DisplaySetNumber', x00720203: 'DisplaySetLabel', x00720204: 'DisplaySetPresentationGroup', x00720206: 'DisplaySetPresentationGroupDescr', x00720208: 'PartialDataDisplayHandling', x00720210: 'SynchronizedScrollingSequence', x00720212: 'DisplaySetScrollingGroup', x00720214: 'NavigationIndicatorSequence', x00720216: 'NavigationDisplaySet', x00720218: 'ReferenceDisplaySets', x00720300: 'ImageBoxesSequence', x00720302: 'ImageBoxNumber', x00720304: 'ImageBoxLayoutType', x00720306: 'ImageBoxTileHorizontalDimension', x00720308: 'ImageBoxTileVerticalDimension', x00720310: 'ImageBoxScrollDirection', x00720312: 'ImageBoxSmallScrollType', x00720314: 'ImageBoxSmallScrollAmount', x00720316: 'ImageBoxLargeScrollType', x00720318: 'ImageBoxLargeScrollAmount', x00720320: 'ImageBoxOverlapPriority', x00720330: 'CineRelativeToRealTime', x00720400: 'FilterOperationsSequence', x00720402: 'FilterByCategory', x00720404: 'FilterByAttributePresence', x00720406: 'FilterByOperator', x00720432: 'SynchronizedImageBoxList', x00720434: 'TypeOfSynchronization', x00720500: 'BlendingOperationType', x00720510: 'ReformattingOperationType', x00720512: 'ReformattingThickness', x00720514: 'ReformattingInterval', x00720516: 'ReformattingOpInitialViewDir', x00720520: 'RenderingType3D', x00720600: 'SortingOperationsSequence', x00720602: 'SortByCategory', x00720604: 'SortingDirection', x00720700: 'DisplaySetPatientOrientation', x00720702: 'VOIType', x00720704: 'PseudoColorType', x00720706: 'ShowGrayscaleInverted', x00720710: 'ShowImageTrueSizeFlag', x00720712: 'ShowGraphicAnnotationFlag', x00720714: 'ShowPatientDemographicsFlag', x00720716: 'ShowAcquisitionTechniquesFlag', x00720717: 'DisplaySetHorizontalJustification', x00720718: 'DisplaySetVerticalJustification', x00741000: 'UnifiedProcedureStepState', x00741002: 'UPSProgressInformationSequence', x00741004: 'UnifiedProcedureStepProgress', x00741006: 'UnifiedProcedureStepProgressDescr', x00741008: 'UnifiedProcedureStepComURISeq', x0074100a: 'ContactURI', x0074100c: 'ContactDisplayName', x00741020: 'BeamTaskSequence', x00741022: 'BeamTaskType', x00741024: 'BeamOrderIndex', x00741030: 'DeliveryVerificationImageSequence', x00741032: 'VerificationImageTiming', x00741034: 'DoubleExposureFlag', x00741036: 'DoubleExposureOrdering', x00741038: 'DoubleExposureMeterset', x0074103a: 'DoubleExposureFieldDelta', x00741040: 'RelatedReferenceRTImageSequence', x00741042: 'GeneralMachineVerificationSequence', x00741044: 'ConventionalMachineVerificationSeq', x00741046: 'IonMachineVerificationSequence', x00741048: 'FailedAttributesSequence', x0074104a: 'OverriddenAttributesSequence', x0074104c: 'ConventionalControlPointVerifySeq', x0074104e: 'IonControlPointVerificationSeq', x00741050: 'AttributeOccurrenceSequence', x00741052: 'AttributeOccurrencePointer', x00741054: 'AttributeItemSelector', x00741056: 'AttributeOccurrencePrivateCreator', x00741200: 'ScheduledProcedureStepPriority', x00741202: 'StudyListLabel', x00741204: 'ProcedureStepLabel', x00741210: 'ScheduledProcessingParametersSeq', x00741212: 'PerformedProcessingParametersSeq', x00741216: 'UPSPerformedProcedureSequence', x00741220: 'RelatedProcedureStepSequence', x00741222: 'ProcedureStepRelationshipType', x00741230: 'DeletionLock', x00741234: 'ReceivingAE', x00741236: 'RequestingAE', x00741238: 'ReasonForCancellation', x00741242: 'SCPStatus', x00741244: 'SubscriptionListStatus', x00741246: 'UPSListStatus', x00880130: 'StorageMediaFileSetID', x00880140: 'StorageMediaFileSetUID', x00880200: 'IconImageSequence', x00880904: 'TopicTitle', x00880906: 'TopicSubject', x00880910: 'TopicAuthor', x00880912: 'TopicKeywords', x01000410: 'SOPInstanceStatus', x01000420: 'SOPAuthorizationDateAndTime', x01000424: 'SOPAuthorizationComment', x01000426: 'AuthorizationEquipmentCertNumber', x04000005: 'MACIDNumber', x04000010: 'MACCalculationTransferSyntaxUID', x04000015: 'MACAlgorithm', x04000020: 'DataElementsSigned', x04000100: 'DigitalSignatureUID', x04000105: 'DigitalSignatureDateTime', x04000110: 'CertificateType', x04000115: 'CertificateOfSigner', x04000120: 'Signature', x04000305: 'CertifiedTimestampType', x04000310: 'CertifiedTimestamp', x04000401: 'DigitalSignaturePurposeCodeSeq', x04000402: 'ReferencedDigitalSignatureSeq', x04000403: 'ReferencedSOPInstanceMACSeq', x04000404: 'MAC', x04000500: 'EncryptedAttributesSequence', x04000510: 'EncryptedContentTransferSyntaxUID', x04000520: 'EncryptedContent', x04000550: 'ModifiedAttributesSequence', x04000561: 'OriginalAttributesSequence', x04000562: 'AttributeModificationDateTime', x04000563: 'ModifyingSystem', x04000564: 'SourceOfPreviousValues', x04000565: 'ReasonForTheAttributeModification', x1000xxx0: 'EscapeTriplet', x1000xxx1: 'RunLengthTriplet', x1000xxx2: 'HuffmanTableSize', x1000xxx3: 'HuffmanTableTriplet', x1000xxx4: 'ShiftTableSize', x1000xxx5: 'ShiftTableTriplet', x1010xxxx: 'ZonalMap', x20000010: 'NumberOfCopies', x2000001e: 'PrinterConfigurationSequence', x20000020: 'PrintPriority', x20000030: 'MediumType', x20000040: 'FilmDestination', x20000050: 'FilmSessionLabel', x20000060: 'MemoryAllocation', x20000061: 'MaximumMemoryAllocation', x20000062: 'ColorImagePrintingFlag', x20000063: 'CollationFlag', x20000065: 'AnnotationFlag', x20000067: 'ImageOverlayFlag', x20000069: 'PresentationLUTFlag', x2000006a: 'ImageBoxPresentationLUTFlag', x200000a0: 'MemoryBitDepth', x200000a1: 'PrintingBitDepth', x200000a2: 'MediaInstalledSequence', x200000a4: 'OtherMediaAvailableSequence', x200000a8: 'SupportedImageDisplayFormatSeq', x20000500: 'ReferencedFilmBoxSequence', x20000510: 'ReferencedStoredPrintSequence', x20100010: 'ImageDisplayFormat', x20100030: 'AnnotationDisplayFormatID', x20100040: 'FilmOrientation', x20100050: 'FilmSizeID', x20100052: 'PrinterResolutionID', x20100054: 'DefaultPrinterResolutionID', x20100060: 'MagnificationType', x20100080: 'SmoothingType', x201000a6: 'DefaultMagnificationType', x201000a7: 'OtherMagnificationTypesAvailable', x201000a8: 'DefaultSmoothingType', x201000a9: 'OtherSmoothingTypesAvailable', x20100100: 'BorderDensity', x20100110: 'EmptyImageDensity', x20100120: 'MinDensity', x20100130: 'MaxDensity', x20100140: 'Trim', x20100150: 'ConfigurationInformation', x20100152: 'ConfigurationInformationDescr', x20100154: 'MaximumCollatedFilms', x2010015e: 'Illumination', x20100160: 'ReflectedAmbientLight', x20100376: 'PrinterPixelSpacing', x20100500: 'ReferencedFilmSessionSequence', x20100510: 'ReferencedImageBoxSequence', x20100520: 'ReferencedBasicAnnotationBoxSeq', x20200010: 'ImageBoxPosition', x20200020: 'Polarity', x20200030: 'RequestedImageSize', x20200040: 'RequestedDecimate-CropBehavior', x20200050: 'RequestedResolutionID', x202000a0: 'RequestedImageSizeFlag', x202000a2: 'DecimateCropResult', x20200110: 'BasicGrayscaleImageSequence', x20200111: 'BasicColorImageSequence', x20200130: 'ReferencedImageOverlayBoxSequence', x20200140: 'ReferencedVOILUTBoxSequence', x20300010: 'AnnotationPosition', x20300020: 'TextString', x20400010: 'ReferencedOverlayPlaneSequence', x20400011: 'ReferencedOverlayPlaneGroups', x20400020: 'OverlayPixelDataSequence', x20400060: 'OverlayMagnificationType', x20400070: 'OverlaySmoothingType', x20400072: 'OverlayOrImageMagnification', x20400074: 'MagnifyToNumberOfColumns', x20400080: 'OverlayForegroundDensity', x20400082: 'OverlayBackgroundDensity', x20400090: 'OverlayMode', x20400100: 'ThresholdDensity', x20400500: 'ReferencedImageBoxSequenceRetired', x20500010: 'PresentationLUTSequence', x20500020: 'PresentationLUTShape', x20500500: 'ReferencedPresentationLUTSequence', x21000010: 'PrintJobID', x21000020: 'ExecutionStatus', x21000030: 'ExecutionStatusInfo', x21000040: 'CreationDate', x21000050: 'CreationTime', x21000070: 'Originator', x21000140: 'DestinationAE', x21000160: 'OwnerID', x21000170: 'NumberOfFilms', x21000500: 'ReferencedPrintJobSequencePullStoredPrint', x21100010: 'PrinterStatus', x21100020: 'PrinterStatusInfo', x21100030: 'PrinterName', x21100099: 'PrintQueueID', x21200010: 'QueueStatus', x21200050: 'PrintJobDescriptionSequence', x21200070: 'ReferencedPrintJobSequence', x21300010: 'PrintManagementCapabilitiesSeq', x21300015: 'PrinterCharacteristicsSequence', x21300030: 'FilmBoxContentSequence', x21300040: 'ImageBoxContentSequence', x21300050: 'AnnotationContentSequence', x21300060: 'ImageOverlayBoxContentSequence', x21300080: 'PresentationLUTContentSequence', x213000a0: 'ProposedStudySequence', x213000c0: 'OriginalImageSequence', x22000001: 'LabelFromInfoExtractedFromInstance', x22000002: 'LabelText', x22000003: 'LabelStyleSelection', x22000004: 'MediaDisposition', x22000005: 'BarcodeValue', x22000006: 'BarcodeSymbology', x22000007: 'AllowMediaSplitting', x22000008: 'IncludeNonDICOMObjects', x22000009: 'IncludeDisplayApplication', x2200000a: 'SaveCompInstancesAfterMediaCreate', x2200000b: 'TotalNumberMediaPiecesCreated', x2200000c: 'RequestedMediaApplicationProfile', x2200000d: 'ReferencedStorageMediaSequence', x2200000e: 'FailureAttributes', x2200000f: 'AllowLossyCompression', x22000020: 'RequestPriority', x30020002: 'RTImageLabel', x30020003: 'RTImageName', x30020004: 'RTImageDescription', x3002000a: 'ReportedValuesOrigin', x3002000c: 'RTImagePlane', x3002000d: 'XRayImageReceptorTranslation', x3002000e: 'XRayImageReceptorAngle', x30020010: 'RTImageOrientation', x30020011: 'ImagePlanePixelSpacing', x30020012: 'RTImagePosition', x30020020: 'RadiationMachineName', x30020022: 'RadiationMachineSAD', x30020024: 'RadiationMachineSSD', x30020026: 'RTImageSID', x30020028: 'SourceToReferenceObjectDistance', x30020029: 'FractionNumber', x30020030: 'ExposureSequence', x30020032: 'MetersetExposure', x30020034: 'DiaphragmPosition', x30020040: 'FluenceMapSequence', x30020041: 'FluenceDataSource', x30020042: 'FluenceDataScale', x30020051: 'FluenceMode', x30020052: 'FluenceModeID', x30040001: 'DVHType', x30040002: 'DoseUnits', x30040004: 'DoseType', x30040006: 'DoseComment', x30040008: 'NormalizationPoint', x3004000a: 'DoseSummationType', x3004000c: 'GridFrameOffsetVector', x3004000e: 'DoseGridScaling', x30040010: 'RTDoseROISequence', x30040012: 'DoseValue', x30040014: 'TissueHeterogeneityCorrection', x30040040: 'DVHNormalizationPoint', x30040042: 'DVHNormalizationDoseValue', x30040050: 'DVHSequence', x30040052: 'DVHDoseScaling', x30040054: 'DVHVolumeUnits', x30040056: 'DVHNumberOfBins', x30040058: 'DVHData', x30040060: 'DVHReferencedROISequence', x30040062: 'DVHROIContributionType', x30040070: 'DVHMinimumDose', x30040072: 'DVHMaximumDose', x30040074: 'DVHMeanDose', x30060002: 'StructureSetLabel', x30060004: 'StructureSetName', x30060006: 'StructureSetDescription', x30060008: 'StructureSetDate', x30060009: 'StructureSetTime', x30060010: 'ReferencedFrameOfReferenceSequence', x30060012: 'RTReferencedStudySequence', x30060014: 'RTReferencedSeriesSequence', x30060016: 'ContourImageSequence', x30060020: 'StructureSetROISequence', x30060022: 'ROINumber', x30060024: 'ReferencedFrameOfReferenceUID', x30060026: 'ROIName', x30060028: 'ROIDescription', x3006002a: 'ROIDisplayColor', x3006002c: 'ROIVolume', x30060030: 'RTRelatedROISequence', x30060033: 'RTROIRelationship', x30060036: 'ROIGenerationAlgorithm', x30060038: 'ROIGenerationDescription', x30060039: 'ROIContourSequence', x30060040: 'ContourSequence', x30060042: 'ContourGeometricType', x30060044: 'ContourSlabThickness', x30060045: 'ContourOffsetVector', x30060046: 'NumberOfContourPoints', x30060048: 'ContourNumber', x30060049: 'AttachedContours', x30060050: 'ContourData', x30060080: 'RTROIObservationsSequence', x30060082: 'ObservationNumber', x30060084: 'ReferencedROINumber', x30060085: 'ROIObservationLabel', x30060086: 'RTROIIdentificationCodeSequence', x30060088: 'ROIObservationDescription', x300600a0: 'RelatedRTROIObservationsSequence', x300600a4: 'RTROIInterpretedType', x300600a6: 'ROIInterpreter', x300600b0: 'ROIPhysicalPropertiesSequence', x300600b2: 'ROIPhysicalProperty', x300600b4: 'ROIPhysicalPropertyValue', x300600b6: 'ROIElementalCompositionSequence', x300600b7: 'ROIElementalCompAtomicNumber', x300600b8: 'ROIElementalCompAtomicMassFraction', x300600c0: 'FrameOfReferenceRelationshipSeq', x300600c2: 'RelatedFrameOfReferenceUID', x300600c4: 'FrameOfReferenceTransformType', x300600c6: 'FrameOfReferenceTransformMatrix', x300600c8: 'FrameOfReferenceTransformComment', x30080010: 'MeasuredDoseReferenceSequence', x30080012: 'MeasuredDoseDescription', x30080014: 'MeasuredDoseType', x30080016: 'MeasuredDoseValue', x30080020: 'TreatmentSessionBeamSequence', x30080021: 'TreatmentSessionIonBeamSequence', x30080022: 'CurrentFractionNumber', x30080024: 'TreatmentControlPointDate', x30080025: 'TreatmentControlPointTime', x3008002a: 'TreatmentTerminationStatus', x3008002b: 'TreatmentTerminationCode', x3008002c: 'TreatmentVerificationStatus', x30080030: 'ReferencedTreatmentRecordSequence', x30080032: 'SpecifiedPrimaryMeterset', x30080033: 'SpecifiedSecondaryMeterset', x30080036: 'DeliveredPrimaryMeterset', x30080037: 'DeliveredSecondaryMeterset', x3008003a: 'SpecifiedTreatmentTime', x3008003b: 'DeliveredTreatmentTime', x30080040: 'ControlPointDeliverySequence', x30080041: 'IonControlPointDeliverySequence', x30080042: 'SpecifiedMeterset', x30080044: 'DeliveredMeterset', x30080045: 'MetersetRateSet', x30080046: 'MetersetRateDelivered', x30080047: 'ScanSpotMetersetsDelivered', x30080048: 'DoseRateDelivered', x30080050: 'TreatmentSummaryCalcDoseRefSeq', x30080052: 'CumulativeDoseToDoseReference', x30080054: 'FirstTreatmentDate', x30080056: 'MostRecentTreatmentDate', x3008005a: 'NumberOfFractionsDelivered', x30080060: 'OverrideSequence', x30080061: 'ParameterSequencePointer', x30080062: 'OverrideParameterPointer', x30080063: 'ParameterItemIndex', x30080064: 'MeasuredDoseReferenceNumber', x30080065: 'ParameterPointer', x30080066: 'OverrideReason', x30080068: 'CorrectedParameterSequence', x3008006a: 'CorrectionValue', x30080070: 'CalculatedDoseReferenceSequence', x30080072: 'CalculatedDoseReferenceNumber', x30080074: 'CalculatedDoseReferenceDescription', x30080076: 'CalculatedDoseReferenceDoseValue', x30080078: 'StartMeterset', x3008007a: 'EndMeterset', x30080080: 'ReferencedMeasuredDoseReferenceSeq', x30080082: 'ReferencedMeasuredDoseReferenceNum', x30080090: 'ReferencedCalculatedDoseRefSeq', x30080092: 'ReferencedCalculatedDoseRefNumber', x300800a0: 'BeamLimitingDeviceLeafPairsSeq', x300800b0: 'RecordedWedgeSequence', x300800c0: 'RecordedCompensatorSequence', x300800d0: 'RecordedBlockSequence', x300800e0: 'TreatmentSummaryMeasuredDoseRefSeq', x300800f0: 'RecordedSnoutSequence', x300800f2: 'RecordedRangeShifterSequence', x300800f4: 'RecordedLateralSpreadingDeviceSeq', x300800f6: 'RecordedRangeModulatorSequence', x30080100: 'RecordedSourceSequence', x30080105: 'SourceSerialNumber', x30080110: 'TreatmentSessionAppSetupSeq', x30080116: 'ApplicationSetupCheck', x30080120: 'RecordedBrachyAccessoryDeviceSeq', x30080122: 'ReferencedBrachyAccessoryDeviceNum', x30080130: 'RecordedChannelSequence', x30080132: 'SpecifiedChannelTotalTime', x30080134: 'DeliveredChannelTotalTime', x30080136: 'SpecifiedNumberOfPulses', x30080138: 'DeliveredNumberOfPulses', x3008013a: 'SpecifiedPulseRepetitionInterval', x3008013c: 'DeliveredPulseRepetitionInterval', x30080140: 'RecordedSourceApplicatorSequence', x30080142: 'ReferencedSourceApplicatorNumber', x30080150: 'RecordedChannelShieldSequence', x30080152: 'ReferencedChannelShieldNumber', x30080160: 'BrachyControlPointDeliveredSeq', x30080162: 'SafePositionExitDate', x30080164: 'SafePositionExitTime', x30080166: 'SafePositionReturnDate', x30080168: 'SafePositionReturnTime', x30080200: 'CurrentTreatmentStatus', x30080202: 'TreatmentStatusComment', x30080220: 'FractionGroupSummarySequence', x30080223: 'ReferencedFractionNumber', x30080224: 'FractionGroupType', x30080230: 'BeamStopperPosition', x30080240: 'FractionStatusSummarySequence', x30080250: 'TreatmentDate', x30080251: 'TreatmentTime', x300a0002: 'RTPlanLabel', x300a0003: 'RTPlanName', x300a0004: 'RTPlanDescription', x300a0006: 'RTPlanDate', x300a0007: 'RTPlanTime', x300a0009: 'TreatmentProtocols', x300a000a: 'PlanIntent', x300a000b: 'TreatmentSites', x300a000c: 'RTPlanGeometry', x300a000e: 'PrescriptionDescription', x300a0010: 'DoseReferenceSequence', x300a0012: 'DoseReferenceNumber', x300a0013: 'DoseReferenceUID', x300a0014: 'DoseReferenceStructureType', x300a0015: 'NominalBeamEnergyUnit', x300a0016: 'DoseReferenceDescription', x300a0018: 'DoseReferencePointCoordinates', x300a001a: 'NominalPriorDose', x300a0020: 'DoseReferenceType', x300a0021: 'ConstraintWeight', x300a0022: 'DeliveryWarningDose', x300a0023: 'DeliveryMaximumDose', x300a0025: 'TargetMinimumDose', x300a0026: 'TargetPrescriptionDose', x300a0027: 'TargetMaximumDose', x300a0028: 'TargetUnderdoseVolumeFraction', x300a002a: 'OrganAtRiskFullVolumeDose', x300a002b: 'OrganAtRiskLimitDose', x300a002c: 'OrganAtRiskMaximumDose', x300a002d: 'OrganAtRiskOverdoseVolumeFraction', x300a0040: 'ToleranceTableSequence', x300a0042: 'ToleranceTableNumber', x300a0043: 'ToleranceTableLabel', x300a0044: 'GantryAngleTolerance', x300a0046: 'BeamLimitingDeviceAngleTolerance', x300a0048: 'BeamLimitingDeviceToleranceSeq', x300a004a: 'BeamLimitingDevicePositionTol', x300a004b: 'SnoutPositionTolerance', x300a004c: 'PatientSupportAngleTolerance', x300a004e: 'TableTopEccentricAngleTolerance', x300a004f: 'TableTopPitchAngleTolerance', x300a0050: 'TableTopRollAngleTolerance', x300a0051: 'TableTopVerticalPositionTolerance', x300a0052: 'TableTopLongitudinalPositionTol', x300a0053: 'TableTopLateralPositionTolerance', x300a0055: 'RTPlanRelationship', x300a0070: 'FractionGroupSequence', x300a0071: 'FractionGroupNumber', x300a0072: 'FractionGroupDescription', x300a0078: 'NumberOfFractionsPlanned', x300a0079: 'NumberFractionPatternDigitsPerDay', x300a007a: 'RepeatFractionCycleLength', x300a007b: 'FractionPattern', x300a0080: 'NumberOfBeams', x300a0082: 'BeamDoseSpecificationPoint', x300a0084: 'BeamDose', x300a0086: 'BeamMeterset', x300a0088: 'BeamDosePointDepth', x300a0089: 'BeamDosePointEquivalentDepth', x300a008a: 'BeamDosePointSSD', x300a00a0: 'NumberOfBrachyApplicationSetups', x300a00a2: 'BrachyAppSetupDoseSpecPoint', x300a00a4: 'BrachyApplicationSetupDose', x300a00b0: 'BeamSequence', x300a00b2: 'TreatmentMachineName', x300a00b3: 'PrimaryDosimeterUnit', x300a00b4: 'SourceAxisDistance', x300a00b6: 'BeamLimitingDeviceSequence', x300a00b8: 'RTBeamLimitingDeviceType', x300a00ba: 'SourceToBeamLimitingDeviceDistance', x300a00bb: 'IsocenterToBeamLimitingDeviceDist', x300a00bc: 'NumberOfLeafJawPairs', x300a00be: 'LeafPositionBoundaries', x300a00c0: 'BeamNumber', x300a00c2: 'BeamName', x300a00c3: 'BeamDescription', x300a00c4: 'BeamType', x300a00c6: 'RadiationType', x300a00c7: 'HighDoseTechniqueType', x300a00c8: 'ReferenceImageNumber', x300a00ca: 'PlannedVerificationImageSequence', x300a00cc: 'ImagingDeviceSpecificAcqParams', x300a00ce: 'TreatmentDeliveryType', x300a00d0: 'NumberOfWedges', x300a00d1: 'WedgeSequence', x300a00d2: 'WedgeNumber', x300a00d3: 'WedgeType', x300a00d4: 'WedgeID', x300a00d5: 'WedgeAngle', x300a00d6: 'WedgeFactor', x300a00d7: 'TotalWedgeTrayWaterEquivThickness', x300a00d8: 'WedgeOrientation', x300a00d9: 'IsocenterToWedgeTrayDistance', x300a00da: 'SourceToWedgeTrayDistance', x300a00db: 'WedgeThinEdgePosition', x300a00dc: 'BolusID', x300a00dd: 'BolusDescription', x300a00e0: 'NumberOfCompensators', x300a00e1: 'MaterialID', x300a00e2: 'TotalCompensatorTrayFactor', x300a00e3: 'CompensatorSequence', x300a00e4: 'CompensatorNumber', x300a00e5: 'CompensatorID', x300a00e6: 'SourceToCompensatorTrayDistance', x300a00e7: 'CompensatorRows', x300a00e8: 'CompensatorColumns', x300a00e9: 'CompensatorPixelSpacing', x300a00ea: 'CompensatorPosition', x300a00eb: 'CompensatorTransmissionData', x300a00ec: 'CompensatorThicknessData', x300a00ed: 'NumberOfBoli', x300a00ee: 'CompensatorType', x300a00f0: 'NumberOfBlocks', x300a00f2: 'TotalBlockTrayFactor', x300a00f3: 'TotalBlockTrayWaterEquivThickness', x300a00f4: 'BlockSequence', x300a00f5: 'BlockTrayID', x300a00f6: 'SourceToBlockTrayDistance', x300a00f7: 'IsocenterToBlockTrayDistance', x300a00f8: 'BlockType', x300a00f9: 'AccessoryCode', x300a00fa: 'BlockDivergence', x300a00fb: 'BlockMountingPosition', x300a00fc: 'BlockNumber', x300a00fe: 'BlockName', x300a0100: 'BlockThickness', x300a0102: 'BlockTransmission', x300a0104: 'BlockNumberOfPoints', x300a0106: 'BlockData', x300a0107: 'ApplicatorSequence', x300a0108: 'ApplicatorID', x300a0109: 'ApplicatorType', x300a010a: 'ApplicatorDescription', x300a010c: 'CumulativeDoseReferenceCoefficient', x300a010e: 'FinalCumulativeMetersetWeight', x300a0110: 'NumberOfControlPoints', x300a0111: 'ControlPointSequence', x300a0112: 'ControlPointIndex', x300a0114: 'NominalBeamEnergy', x300a0115: 'DoseRateSet', x300a0116: 'WedgePositionSequence', x300a0118: 'WedgePosition', x300a011a: 'BeamLimitingDevicePositionSequence', x300a011c: 'LeafJawPositions', x300a011e: 'GantryAngle', x300a011f: 'GantryRotationDirection', x300a0120: 'BeamLimitingDeviceAngle', x300a0121: 'BeamLimitingDeviceRotateDirection', x300a0122: 'PatientSupportAngle', x300a0123: 'PatientSupportRotationDirection', x300a0124: 'TableTopEccentricAxisDistance', x300a0125: 'TableTopEccentricAngle', x300a0126: 'TableTopEccentricRotateDirection', x300a0128: 'TableTopVerticalPosition', x300a0129: 'TableTopLongitudinalPosition', x300a012a: 'TableTopLateralPosition', x300a012c: 'IsocenterPosition', x300a012e: 'SurfaceEntryPoint', x300a0130: 'SourceToSurfaceDistance', x300a0134: 'CumulativeMetersetWeight', x300a0140: 'TableTopPitchAngle', x300a0142: 'TableTopPitchRotationDirection', x300a0144: 'TableTopRollAngle', x300a0146: 'TableTopRollRotationDirection', x300a0148: 'HeadFixationAngle', x300a014a: 'GantryPitchAngle', x300a014c: 'GantryPitchRotationDirection', x300a014e: 'GantryPitchAngleTolerance', x300a0180: 'PatientSetupSequence', x300a0182: 'PatientSetupNumber', x300a0183: 'PatientSetupLabel', x300a0184: 'PatientAdditionalPosition', x300a0190: 'FixationDeviceSequence', x300a0192: 'FixationDeviceType', x300a0194: 'FixationDeviceLabel', x300a0196: 'FixationDeviceDescription', x300a0198: 'FixationDevicePosition', x300a0199: 'FixationDevicePitchAngle', x300a019a: 'FixationDeviceRollAngle', x300a01a0: 'ShieldingDeviceSequence', x300a01a2: 'ShieldingDeviceType', x300a01a4: 'ShieldingDeviceLabel', x300a01a6: 'ShieldingDeviceDescription', x300a01a8: 'ShieldingDevicePosition', x300a01b0: 'SetupTechnique', x300a01b2: 'SetupTechniqueDescription', x300a01b4: 'SetupDeviceSequence', x300a01b6: 'SetupDeviceType', x300a01b8: 'SetupDeviceLabel', x300a01ba: 'SetupDeviceDescription', x300a01bc: 'SetupDeviceParameter', x300a01d0: 'SetupReferenceDescription', x300a01d2: 'TableTopVerticalSetupDisplacement', x300a01d4: 'TableTopLongitudinalSetupDisplace', x300a01d6: 'TableTopLateralSetupDisplacement', x300a0200: 'BrachyTreatmentTechnique', x300a0202: 'BrachyTreatmentType', x300a0206: 'TreatmentMachineSequence', x300a0210: 'SourceSequence', x300a0212: 'SourceNumber', x300a0214: 'SourceType', x300a0216: 'SourceManufacturer', x300a0218: 'ActiveSourceDiameter', x300a021a: 'ActiveSourceLength', x300a0222: 'SourceEncapsulationNomThickness', x300a0224: 'SourceEncapsulationNomTransmission', x300a0226: 'SourceIsotopeName', x300a0228: 'SourceIsotopeHalfLife', x300a0229: 'SourceStrengthUnits', x300a022a: 'ReferenceAirKermaRate', x300a022b: 'SourceStrength', x300a022c: 'SourceStrengthReferenceDate', x300a022e: 'SourceStrengthReferenceTime', x300a0230: 'ApplicationSetupSequence', x300a0232: 'ApplicationSetupType', x300a0234: 'ApplicationSetupNumber', x300a0236: 'ApplicationSetupName', x300a0238: 'ApplicationSetupManufacturer', x300a0240: 'TemplateNumber', x300a0242: 'TemplateType', x300a0244: 'TemplateName', x300a0250: 'TotalReferenceAirKerma', x300a0260: 'BrachyAccessoryDeviceSequence', x300a0262: 'BrachyAccessoryDeviceNumber', x300a0263: 'BrachyAccessoryDeviceID', x300a0264: 'BrachyAccessoryDeviceType', x300a0266: 'BrachyAccessoryDeviceName', x300a026a: 'BrachyAccessoryDeviceNomThickness', x300a026c: 'BrachyAccessoryDevNomTransmission', x300a0280: 'ChannelSequence', x300a0282: 'ChannelNumber', x300a0284: 'ChannelLength', x300a0286: 'ChannelTotalTime', x300a0288: 'SourceMovementType', x300a028a: 'NumberOfPulses', x300a028c: 'PulseRepetitionInterval', x300a0290: 'SourceApplicatorNumber', x300a0291: 'SourceApplicatorID', x300a0292: 'SourceApplicatorType', x300a0294: 'SourceApplicatorName', x300a0296: 'SourceApplicatorLength', x300a0298: 'SourceApplicatorManufacturer', x300a029c: 'SourceApplicatorWallNomThickness', x300a029e: 'SourceApplicatorWallNomTrans', x300a02a0: 'SourceApplicatorStepSize', x300a02a2: 'TransferTubeNumber', x300a02a4: 'TransferTubeLength', x300a02b0: 'ChannelShieldSequence', x300a02b2: 'ChannelShieldNumber', x300a02b3: 'ChannelShieldID', x300a02b4: 'ChannelShieldName', x300a02b8: 'ChannelShieldNominalThickness', x300a02ba: 'ChannelShieldNominalTransmission', x300a02c8: 'FinalCumulativeTimeWeight', x300a02d0: 'BrachyControlPointSequence', x300a02d2: 'ControlPointRelativePosition', x300a02d4: 'ControlPoint3DPosition', x300a02d6: 'CumulativeTimeWeight', x300a02e0: 'CompensatorDivergence', x300a02e1: 'CompensatorMountingPosition', x300a02e2: 'SourceToCompensatorDistance', x300a02e3: 'TotalCompTrayWaterEquivThickness', x300a02e4: 'IsocenterToCompensatorTrayDistance', x300a02e5: 'CompensatorColumnOffset', x300a02e6: 'IsocenterToCompensatorDistances', x300a02e7: 'CompensatorRelStoppingPowerRatio', x300a02e8: 'CompensatorMillingToolDiameter', x300a02ea: 'IonRangeCompensatorSequence', x300a02eb: 'CompensatorDescription', x300a0302: 'RadiationMassNumber', x300a0304: 'RadiationAtomicNumber', x300a0306: 'RadiationChargeState', x300a0308: 'ScanMode', x300a030a: 'VirtualSourceAxisDistances', x300a030c: 'SnoutSequence', x300a030d: 'SnoutPosition', x300a030f: 'SnoutID', x300a0312: 'NumberOfRangeShifters', x300a0314: 'RangeShifterSequence', x300a0316: 'RangeShifterNumber', x300a0318: 'RangeShifterID', x300a0320: 'RangeShifterType', x300a0322: 'RangeShifterDescription', x300a0330: 'NumberOfLateralSpreadingDevices', x300a0332: 'LateralSpreadingDeviceSequence', x300a0334: 'LateralSpreadingDeviceNumber', x300a0336: 'LateralSpreadingDeviceID', x300a0338: 'LateralSpreadingDeviceType', x300a033a: 'LateralSpreadingDeviceDescription', x300a033c: 'LateralSpreadingDevWaterEquivThick', x300a0340: 'NumberOfRangeModulators', x300a0342: 'RangeModulatorSequence', x300a0344: 'RangeModulatorNumber', x300a0346: 'RangeModulatorID', x300a0348: 'RangeModulatorType', x300a034a: 'RangeModulatorDescription', x300a034c: 'BeamCurrentModulationID', x300a0350: 'PatientSupportType', x300a0352: 'PatientSupportID', x300a0354: 'PatientSupportAccessoryCode', x300a0356: 'FixationLightAzimuthalAngle', x300a0358: 'FixationLightPolarAngle', x300a035a: 'MetersetRate', x300a0360: 'RangeShifterSettingsSequence', x300a0362: 'RangeShifterSetting', x300a0364: 'IsocenterToRangeShifterDistance', x300a0366: 'RangeShifterWaterEquivThickness', x300a0370: 'LateralSpreadingDeviceSettingsSeq', x300a0372: 'LateralSpreadingDeviceSetting', x300a0374: 'IsocenterToLateralSpreadingDevDist', x300a0380: 'RangeModulatorSettingsSequence', x300a0382: 'RangeModulatorGatingStartValue', x300a0384: 'RangeModulatorGatingStopValue', x300a038a: 'IsocenterToRangeModulatorDistance', x300a0390: 'ScanSpotTuneID', x300a0392: 'NumberOfScanSpotPositions', x300a0394: 'ScanSpotPositionMap', x300a0396: 'ScanSpotMetersetWeights', x300a0398: 'ScanningSpotSize', x300a039a: 'NumberOfPaintings', x300a03a0: 'IonToleranceTableSequence', x300a03a2: 'IonBeamSequence', x300a03a4: 'IonBeamLimitingDeviceSequence', x300a03a6: 'IonBlockSequence', x300a03a8: 'IonControlPointSequence', x300a03aa: 'IonWedgeSequence', x300a03ac: 'IonWedgePositionSequence', x300a0401: 'ReferencedSetupImageSequence', x300a0402: 'SetupImageComment', x300a0410: 'MotionSynchronizationSequence', x300a0412: 'ControlPointOrientation', x300a0420: 'GeneralAccessorySequence', x300a0421: 'GeneralAccessoryID', x300a0422: 'GeneralAccessoryDescription', x300a0423: 'GeneralAccessoryType', x300a0424: 'GeneralAccessoryNumber', x300c0002: 'ReferencedRTPlanSequence', x300c0004: 'ReferencedBeamSequence', x300c0006: 'ReferencedBeamNumber', x300c0007: 'ReferencedReferenceImageNumber', x300c0008: 'StartCumulativeMetersetWeight', x300c0009: 'EndCumulativeMetersetWeight', x300c000a: 'ReferencedBrachyAppSetupSeq', x300c000c: 'ReferencedBrachyAppSetupNumber', x300c000e: 'ReferencedSourceNumber', x300c0020: 'ReferencedFractionGroupSequence', x300c0022: 'ReferencedFractionGroupNumber', x300c0040: 'ReferencedVerificationImageSeq', x300c0042: 'ReferencedReferenceImageSequence', x300c0050: 'ReferencedDoseReferenceSequence', x300c0051: 'ReferencedDoseReferenceNumber', x300c0055: 'BrachyReferencedDoseReferenceSeq', x300c0060: 'ReferencedStructureSetSequence', x300c006a: 'ReferencedPatientSetupNumber', x300c0080: 'ReferencedDoseSequence', x300c00a0: 'ReferencedToleranceTableNumber', x300c00b0: 'ReferencedBolusSequence', x300c00c0: 'ReferencedWedgeNumber', x300c00d0: 'ReferencedCompensatorNumber', x300c00e0: 'ReferencedBlockNumber', x300c00f0: 'ReferencedControlPointIndex', x300c00f2: 'ReferencedControlPointSequence', x300c00f4: 'ReferencedStartControlPointIndex', x300c00f6: 'ReferencedStopControlPointIndex', x300c0100: 'ReferencedRangeShifterNumber', x300c0102: 'ReferencedLateralSpreadingDevNum', x300c0104: 'ReferencedRangeModulatorNumber', x300e0002: 'ApprovalStatus', x300e0004: 'ReviewDate', x300e0005: 'ReviewTime', x300e0008: 'ReviewerName', x40000000: 'TextGroupLength', x40000010: 'Arbitrary', x40004000: 'TextComments', x40080040: 'ResultsID', x40080042: 'ResultsIDIssuer', x40080050: 'ReferencedInterpretationSequence', x40080100: 'InterpretationRecordedDate', x40080101: 'InterpretationRecordedTime', x40080102: 'InterpretationRecorder', x40080103: 'ReferenceToRecordedSound', x40080108: 'InterpretationTranscriptionDate', x40080109: 'InterpretationTranscriptionTime', x4008010a: 'InterpretationTranscriber', x4008010b: 'InterpretationText', x4008010c: 'InterpretationAuthor', x40080111: 'InterpretationApproverSequence', x40080112: 'InterpretationApprovalDate', x40080113: 'InterpretationApprovalTime', x40080114: 'PhysicianApprovingInterpretation', x40080115: 'InterpretationDiagnosisDescription', x40080117: 'InterpretationDiagnosisCodeSeq', x40080118: 'ResultsDistributionListSequence', x40080119: 'DistributionName', x4008011a: 'DistributionAddress', x40080200: 'InterpretationID', x40080202: 'InterpretationIDIssuer', x40080210: 'InterpretationTypeID', x40080212: 'InterpretationStatusID', x40080300: 'Impressions', x40084000: 'ResultsComments', x4ffe0001: 'MACParametersSequence', x50xx0005: 'CurveDimensions', x50xx0010: 'NumberOfPoints', x50xx0020: 'TypeOfData', x50xx0022: 'CurveDescription', x50xx0030: 'AxisUnits', x50xx0040: 'AxisLabels', x50xx0103: 'DataValueRepresentation', x50xx0104: 'MinimumCoordinateValue', x50xx0105: 'MaximumCoordinateValue', x50xx0106: 'CurveRange', x50xx0110: 'CurveDataDescriptor', x50xx0112: 'CoordinateStartValue', x50xx0114: 'CoordinateStepValue', x50xx1001: 'CurveActivationLayer', x50xx2000: 'AudioType', x50xx2002: 'AudioSampleFormat', x50xx2004: 'NumberOfChannels', x50xx2006: 'NumberOfSamples', x50xx2008: 'SampleRate', x50xx200a: 'TotalTime', x50xx200c: 'AudioSampleData', x50xx200e: 'AudioComments', x50xx2500: 'CurveLabel', x50xx2600: 'CurveReferencedOverlaySequence', x50xx2610: 'ReferencedOverlayGroup', x50xx3000: 'CurveData', x52009229: 'SharedFunctionalGroupsSequence', x52009230: 'PerFrameFunctionalGroupsSequence', x54000100: 'WaveformSequence', x54000110: 'ChannelMinimumValue', x54000112: 'ChannelMaximumValue', x54001004: 'WaveformBitsAllocated', x54001006: 'WaveformSampleInterpretation', x5400100a: 'WaveformPaddingValue', x54001010: 'WaveformData', x56000010: 'FirstOrderPhaseCorrectionAngle', x56000020: 'SpectroscopyData', x60000000: 'OverlayGroupLength', x60xx0010: 'OverlayRows', x60xx0011: 'OverlayColumns', x60xx0012: 'OverlayPlanes', x60xx0015: 'NumberOfFramesInOverlay', x60xx0022: 'OverlayDescription', x60xx0040: 'OverlayType', x60xx0045: 'OverlaySubtype', x60xx0050: 'OverlayOrigin', x60xx0051: 'ImageFrameOrigin', x60xx0052: 'OverlayPlaneOrigin', x60xx0060: 'OverlayCompressionCode', x60xx0061: 'OverlayCompressionOriginator', x60xx0062: 'OverlayCompressionLabel', x60xx0063: 'OverlayCompressionDescription', x60xx0066: 'OverlayCompressionStepPointers', x60xx0068: 'OverlayRepeatInterval', x60xx0069: 'OverlayBitsGrouped', x60xx0100: 'OverlayBitsAllocated', x60xx0102: 'OverlayBitPosition', x60xx0110: 'OverlayFormat', x60xx0200: 'OverlayLocation', x60xx0800: 'OverlayCodeLabel', x60xx0802: 'OverlayNumberOfTables', x60xx0803: 'OverlayCodeTableLocation', x60xx0804: 'OverlayBitsForCodeWord', x60xx1001: 'OverlayActivationLayer', x60xx1100: 'OverlayDescriptorGray', x60xx1101: 'OverlayDescriptorRed', x60xx1102: 'OverlayDescriptorGreen', x60xx1103: 'OverlayDescriptorBlue', x60xx1200: 'OverlaysGray', x60xx1201: 'OverlaysRed', x60xx1202: 'OverlaysGreen', x60xx1203: 'OverlaysBlue', x60xx1301: 'ROIArea', x60xx1302: 'ROIMean', x60xx1303: 'ROIStandardDeviation', x60xx1500: 'OverlayLabel', x60xx3000: 'OverlayData', x60xx4000: 'OverlayComments', x7fxx0000: 'PixelDataGroupLength', x7fxx0010: 'PixelData', x7fxx0011: 'VariableNextDataGroup', x7fxx0020: 'VariableCoefficientsSDVN', x7fxx0030: 'VariableCoefficientsSDHN', x7fxx0040: 'VariableCoefficientsSDDN', xfffafffa: 'DigitalSignaturesSequence', xfffcfffc: 'DataSetTrailingPadding', xfffee000: 'StartOfItem', xfffee00d: 'EndOfItems', xfffee0dd: 'EndOfSequence' }; DICOMTagDescriptions.init(initialTagDescriptionMap); // Discard original map... initialTagDescriptionMap = null; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"StackManager.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/StackManager.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ StackManager: function () { return StackManager; } }); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); var getImageId; module.watch(require("./getImageId"), { getImageId: function (v) { getImageId = v; } }, 1); var OHIFError; module.watch(require("./classes/OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 2); var stackMap = {}; var configuration = {}; var stackUpdatedCallbacks = []; /** * Loop through the current series and add metadata to the * Cornerstone meta data provider. This will be used to fill information * into the viewport overlays, and to calculate reference lines and orientation markers * @param {Object} stackMap stackMap object * @param {Object} study Study object * @param {Object} displaySet The set of images to make the stack from * @return {Array} Array with image IDs */ function createAndAddStack(stackMap, study, displaySet) { var metadataProvider = OHIF.viewer.metadataProvider; var numImages = displaySet.images.length; var imageIds = []; var imageId; displaySet.images.forEach(function (instance, imageIndex) { var image = instance.getData(); var metaData = { instance: image, // in this context, instance will be the data of the InstanceMetadata object... series: displaySet, // TODO: Check this study: study, numImages: numImages, imageIndex: imageIndex + 1 }; var numberOfFrames = image.numberOfFrames; if (numberOfFrames > 1) { OHIF.log.info('Multiframe image detected'); for (var i = 0; i < numberOfFrames; i++) { metaData.frame = i; imageId = getImageId(image, i); imageIds.push(imageId); metadataProvider.addMetadata(imageId, metaData); } } else { imageId = getImageId(image); imageIds.push(imageId); metadataProvider.addMetadata(imageId, metaData); } }); var stack = { displaySetInstanceUid: displaySet.displaySetInstanceUid, imageIds: imageIds, frameRate: displaySet.frameRate, isClip: displaySet.isClip }; stackMap[displaySet.displaySetInstanceUid] = stack; return stack; } configuration = { createAndAddStack: createAndAddStack }; /** * This object contains all the functions needed for interacting with the stack manager. * Generally, findStack is the only function used. If you want to know when new stacks * come in, you can register a callback with addStackUpdatedCallback. */ var StackManager = { /** * Removes all current stacks */ clearStacks: function () { stackMap = {}; }, /** * Create a stack from an image set, as well as add in the metadata on a per image bases. * @param study The study who's metadata will be added * @param displaySet The set of images to make the stack from * @return {Array} Array with image IDs */ makeAndAddStack: function (study, displaySet) { return configuration.createAndAddStack(stackMap, study, displaySet, stackUpdatedCallbacks); }, /** * Find a stack from the currently created stacks. * @param displaySetInstanceUid The UID of the stack to find. * @returns {*} undefined if not found, otherwise the stack object is returned. */ findStack: function (displaySetInstanceUid) { return stackMap[displaySetInstanceUid]; }, /** * Find a stack or reate one if it has not been created yet * @param study The study who's metadata will be added * @param displaySet The set of images to make the stack from * @return {Array} Array with image IDs */ findOrCreateStack: function (study, displaySet) { var stack = this.findStack(displaySet.displaySetInstanceUid); if (!stack || !stack.imageIds) { stack = this.makeAndAddStack(study, displaySet); } return stack; }, /** * Gets the underlying map of displaySetInstanceUid to stack object. * WARNING: Do not change this object. It directly affects the manager. * @returns {{}} map of displaySetInstanceUid -> stack. */ getAllStacks: function () { return stackMap; }, /** * Adds in a callback to be called on a stack being added / updated. * @param callback must accept at minimum one argument, * which is the stack that was added / updated. */ addStackUpdatedCallback: function (callback) { if (typeof callback !== 'function') { throw new OHIFError('callback must be provided as a function'); } stackUpdatedCallbacks.push(callback); }, /** * Return configuration */ getConfiguration: function () { return configuration; }, /** * Set configuration, in order to provide compatibility * with other systems by overriding this functions * @param {Object} config object with functions to be overrided * * For now, only makeAndAddStack can be overrided */ setConfiguration: function (config) { configuration = config; } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"WLPresets.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/WLPresets.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ WLPresets: function () { return WLPresets; } }); var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 1); var Tracker; module.watch(require("meteor/tracker"), { Tracker: function (v) { Tracker = v; } }, 2); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 3); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 4); var cornerstone; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; } }, 5); var viewportUtils; module.watch(require("./viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 6); var WL_PRESET_CUSTOM = 'WL_PRESET_CUSTOM'; var WL_PRESET_DEFAULT = 'WL_PRESET_DEFAULT'; var WL_STORAGE_KEY = "WindowLevelPresetsDefinitions"; OHIF.viewer.defaultWLPresets = { 0: { id: 'Soft Tissue', wc: 40, ww: 400 }, 1: { id: 'Lung', wc: -600, ww: 1500 }, 2: { id: 'Liver', wc: 90, ww: 150 }, 3: { id: 'Bone', wc: 480, ww: 2500 }, 4: { id: 'Brain', wc: 40, ww: 80 }, 5: {}, 6: {}, 7: {}, 8: {}, 9: {} }; var WindowLevelPresetsManager = /*#__PURE__*/ function () { function WindowLevelPresetsManager() { this.defaults = {}; this.retrieveFunction = null; this.storeFunction = null; this.changeObserver = new Tracker.Dependency(); } var _proto = WindowLevelPresetsManager.prototype; _proto.setRetrieveFunction = function () { function setRetrieveFunction(retrieveFunction) { this.retrieveFunction = retrieveFunction; } return setRetrieveFunction; }(); _proto.setStoreFunction = function () { function setStoreFunction(storeFunction) { this.storeFunction = storeFunction; } return setStoreFunction; }(); /** * Updates the enabledElement data for the Cornerstone element * to reflect the current W/L preset which is applied. * * @param {HTMLElement} element */ _proto.updateElementWLPresetData = function () { function updateElementWLPresetData(element) { var wlPresetData = cornerstone.getElementData(element, 'wlPreset'); var enabledElement = cornerstone.getEnabledElement(element); var viewport = enabledElement.viewport, image = enabledElement.image; var _viewport$voi = viewport.voi, windowCenter = _viewport$voi.windowCenter, windowWidth = _viewport$voi.windowWidth; var presetName; if (windowWidth === image.windowWidth && windowCenter === image.windowCenter) { presetName = WL_PRESET_DEFAULT; } else { var _WLPresets = OHIF.viewer.wlPresets; var currentPreset = Object.values(_WLPresets).find(function (currentPreset) { return windowCenter === currentPreset.wc && windowWidth === currentPreset.ww; }); if (currentPreset) { presetName = currentPreset.id; } else { presetName = WL_PRESET_CUSTOM; } } wlPresetData.name = presetName; wlPresetData.ww = windowWidth; wlPresetData.wc = windowCenter; if (wlPresetData.name === WL_PRESET_CUSTOM) { var custom = wlPresetData.custom || (wlPresetData.custom = Object.create(null)); custom.ww = windowWidth; custom.wc = windowCenter; } } return updateElementWLPresetData; }(); /** * Set specified W/L preset on given element on fallback to default W/L preset if the specified preset is not valid. * @param {String} presetName The desired W/L preset to be applied * @param {HTMLElement} element An enabled viewport DOM Element. */ _proto.applyWLPreset = function () { function applyWLPreset(presetName, element) { var wlPresets = OHIF.viewer.wlPresets; var wlPresetData = cornerstone.getElementData(element, 'wlPreset'); var viewport = cornerstone.getViewport(element); var preset = wlPresets[presetName] || _.findWhere(wlPresets, { id: presetName }); if (presetName === WL_PRESET_CUSTOM && wlPresetData.custom) { viewport.voi.windowWidth = wlPresetData.custom.ww; viewport.voi.windowCenter = wlPresetData.custom.wc; } else if (preset && !_.isEmpty(preset) && preset.id) { presetName = preset.id; viewport.voi.windowWidth = preset.ww; viewport.voi.windowCenter = preset.wc; } else { var enabledElement = cornerstone.getEnabledElement(element); viewport.voi.windowWidth = enabledElement.image.windowWidth; viewport.voi.windowCenter = enabledElement.image.windowCenter; presetName = WL_PRESET_DEFAULT; } wlPresetData.name = presetName; wlPresetData.ww = viewport.voi.windowWidth; wlPresetData.wc = viewport.voi.windowCenter; // Update the viewport cornerstone.setViewport(element, viewport); // Notify other components about W/L Preset changes Session.set('OHIFWlPresetApplied', presetName); } return applyWLPreset; }(); _proto.store = function () { function store(wlPresets) { var _this = this; return new Promise(function (resolve, reject) { if (_this.storeFunction) { _this.storeFunction.call(_this, WL_STORAGE_KEY, wlPresets).then(resolve).catch(reject); } else if (Meteor.userId()) { OHIF.user.setData(WL_STORAGE_KEY, wlPresets).then(resolve).catch(reject); } else { Session.setPersistent(WL_STORAGE_KEY, wlPresets); resolve(); } }).then(function () { return _this.setOHIFWLPresets.call(_this, wlPresets); }); } return store; }(); _proto.retrieve = function () { function retrieve() { var _this2 = this; return new Promise(function (resolve, reject) { if (_this2.retrieveFunction) { _this2.retrieveFunction.call(_this2).then(resolve).catch(reject); } else if (OHIF.user) { try { resolve(OHIF.user.getData(WL_STORAGE_KEY)); } catch (error) { reject(error); } } else { resolve(Session.get(WL_STORAGE_KEY)); } }); } return retrieve; }(); _proto.load = function () { function load() { var _this3 = this; return new Promise(function (resolve, reject) { _this3.retrieve().then(function (wlPresets) { if (wlPresets) { _this3.setOHIFWLPresets.call(_this3, wlPresets); } else { _this3.loadDefaults.call(_this3); } }).catch(function () { return _this3.loadDefaults.call(_this3); }); }); } return load; }(); _proto.applyWLPresetToActiveElement = function () { function applyWLPresetToActiveElement(presetName) { var element = viewportUtils.getActiveViewportElement(); if (!element) { return; } this.applyWLPreset(presetName, element); } return applyWLPresetToActiveElement; }(); /** * Overrides OHIF's wlPresets * @param {Object} wlPresets Object with wlPresets mapping */ _proto.setOHIFWLPresets = function () { function setOHIFWLPresets(wlPresets) { var hasOwn = Object.prototype.hasOwnProperty; var presetMap = Object.create(null); // Objects without prototype have much faster lookup times for (var index in meteorBabelHelpers.sanitizeForInObject(wlPresets)) { if (hasOwn.call(wlPresets, index)) { presetMap[index] = wlPresets[index]; } } OHIF.viewer.wlPresets = presetMap; this.changeObserver.changed(); } return setOHIFWLPresets; }(); _proto.loadDefaults = function () { function loadDefaults() { this.setOHIFWLPresets(OHIF.viewer.defaultWLPresets); } return loadDefaults; }(); _proto.resetDefaults = function () { function resetDefaults() { return this.store(OHIF.viewer.defaultWLPresets); } return resetDefaults; }(); return WindowLevelPresetsManager; }(); /** * Export functions inside WLPresets namespace. */ var WLPresets = new WindowLevelPresetsManager(); Meteor.startup(function () { WLPresets.loadDefaults(); WLPresets.load(); }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"annotateTextUtils.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/annotateTextUtils.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ annotateTextUtils: function () { return annotateTextUtils; } }); var viewportUtils; module.watch(require("./viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 0); var getTextCallback = function (doneChangingTextCallback) { // This handles the text entry for the annotation tool var keyPressHandler = function (e) { // If Enter or Esc are pressed, close the dialog if (e.which === 13 || e.which === 27) { closeHandler(); } }; var closeHandler = function () { dialog.get(0).close(); doneChangingTextCallback(getTextInput.val()); // Reset the text value getTextInput.val(''); // Reset the focus to the active viewport element // This makes the mobile Safari keyboard close var element = viewportUtils.getActiveViewportElement(); $(element).focus(); }; var dialog = $('#annotationDialog'); if (dialog.get(0).open === true) { return; } var getTextInput = $('.annotationTextInput'); // Focus on the text input to open the Safari keyboard getTextInput.focus(); dialog.get(0).showModal(); var confirm = dialog.find('.annotationDialogConfirm'); confirm.off('click'); confirm.on('click', function () { closeHandler(); }); // Use keydown since keypress doesn't handle ESC in Chrome dialog.off('keydown'); dialog.on('keydown', keyPressHandler); }; var changeTextCallback = function (data, eventData, doneChangingTextCallback) { var dialog = $('#relabelAnnotationDialog'); if (dialog.get(0).open === true) { return; } // Is necessary to use Blaze object to not create // circular depencency with helper object (./helpers) if (Blaze._globalHelpers.isTouchDevice()) { // Center the dialog on screen on touch devices dialog.css({ top: 0, left: 0, right: 0, bottom: 0, margin: 'auto' }); } else { // Place the dialog above the tool that is being relabelled dialog.css({ top: eventData.currentPoints.page.y - dialog.outerHeight() - 20, left: eventData.currentPoints.page.x - dialog.outerWidth() / 2 }); } var getTextInput = dialog.find('.annotationTextInput'); var confirm = dialog.find('.relabelConfirm'); var remove = dialog.find('.relabelRemove'); getTextInput.val(data.text); // Focus on the text input to open the Safari keyboard getTextInput.focus(); dialog.get(0).showModal(); confirm.off('click'); confirm.on('click', function () { dialog.get(0).close(); doneChangingTextCallback(data, getTextInput.val()); }); // If the remove button is clicked, delete this marker remove.off('click'); remove.on('click', function () { dialog.get(0).close(); doneChangingTextCallback(data, undefined, true); }); dialog.off('keydown'); dialog.on('keydown', keyPressHandler); var keyPressHandler = function (e) { // If Enter is pressed, close the dialog if (e.which === 13) { closeHandler(); } }; var closeHandler = function () { dialog.get(0).close(); doneChangingTextCallback(data, getTextInput.val()); // Reset the text value getTextInput.val(''); // Reset the focus to the active viewport element // This makes the mobile Safari keyboard close var element = viewportUtils.getActiveViewportElement(); $(element).focus(); }; }; var annotateTextUtils = { getTextCallback: getTextCallback, changeTextCallback: changeTextCallback }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"createStacks.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/createStacks.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ createStacks: function () { return createStacks; } }); var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var ImageSet; module.watch(require("./classes/ImageSet"), { ImageSet: function (v) { ImageSet = v; } }, 1); var isImage; module.watch(require("./isImage"), { isImage: function (v) { isImage = v; } }, 2); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 3); var isMultiFrame = function (instance) { // NumberOfFrames (0028,0008) return instance.getRawValue('x00280008') > 1; }; var makeDisplaySet = function (series, instances) { var instance = instances[0]; var imageSet = new ImageSet(instances); var seriesData = series.getData(); // set appropriate attributes to image set... imageSet.setAttributes({ displaySetInstanceUid: imageSet.uid, // create a local alias for the imageSet UID seriesDate: seriesData.seriesDate, seriesTime: seriesData.seriesTime, seriesInstanceUid: series.getSeriesInstanceUID(), seriesNumber: instance.getRawValue('x00200011'), seriesDescription: instance.getRawValue('x0008103e'), numImageFrames: instances.length, frameRate: instance.getRawValue('x00181063'), modality: instance.getRawValue('x00080060'), isMultiFrame: isMultiFrame(instance) }); // Sort the images in this series if needed var shallSort = !OHIF.utils.ObjectPath.get(Meteor, 'settings.public.ui.sortSeriesByIncomingOrder'); if (shallSort) { imageSet.sortBy(function (a, b) { // Sort by InstanceNumber (0020,0013) return (parseInt(a.getRawValue('x00200013', 0)) || 0) - (parseInt(b.getRawValue('x00200013', 0)) || 0); }); } // Include the first image instance number (after sorted) imageSet.setAttribute('instanceNumber', imageSet.getImage(0).getRawValue('x00200013')); return imageSet; }; var isSingleImageModality = function (modality) { return modality === 'CR' || modality === 'MG' || modality === 'DX'; }; /** * Creates a set of series to be placed in the Study Metadata * The series that appear in the Study Metadata must represent * imaging modalities. * * Furthermore, for drag/drop functionality, * it is easiest if the stack objects also contain information about * which study they are linked to. * * @param study The study instance metadata to be used * @returns {Array} An array of series to be placed in the Study Metadata */ var createStacks = function (study) { // Define an empty array of display sets var displaySets = []; if (!study || !study.getSeriesCount()) { return displaySets; } // Loop through the series (SeriesMetadata) study.forEachSeries(function (series) { // If the series has no instances, skip it if (!series.getInstanceCount()) { return; } // Search through the instances (InstanceMedatada object) of this series // Split Multi-frame instances and Single-image modalities // into their own specific display sets. Place the rest of each // series into another display set. var stackableInstances = []; series.forEachInstance(function (instance) { // All imaging modalities must have a valid value for sopClassUid (x00080016) or rows (x00280010) if (!isImage(instance.getRawValue('x00080016')) && !instance.getRawValue('x00280010')) { return; } var displaySet; if (isMultiFrame(instance)) { displaySet = makeDisplaySet(series, [instance]); displaySet.setAttributes({ isClip: true, studyInstanceUid: study.getStudyInstanceUID(), // Include the study instance Uid for drag/drop purposes numImageFrames: instance.getRawValue('x00280008'), // Override the default value of instances.length instanceNumber: instance.getRawValue('x00200013'), // Include the instance number acquisitionDatetime: instance.getRawValue('x0008002a') // Include the acquisition datetime }); displaySets.push(displaySet); } else if (isSingleImageModality(instance.modality)) { displaySet = makeDisplaySet(series, [instance]); displaySet.setAttributes({ studyInstanceUid: study.getStudyInstanceUID(), // Include the study instance Uid instanceNumber: instance.getRawValue('x00200013'), // Include the instance number acquisitionDatetime: instance.getRawValue('x0008002a') // Include the acquisition datetime }); displaySets.push(displaySet); } else { stackableInstances.push(instance); } }); if (stackableInstances.length) { var displaySet = makeDisplaySet(series, stackableInstances); displaySet.setAttribute('studyInstanceUid', study.getStudyInstanceUID()); displaySets.push(displaySet); } }); return displaySets; }; /** * Expose "createStacks"... */ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"crosshairsSynchronizers.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/crosshairsSynchronizers.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ crosshairsSynchronizers: function () { return crosshairsSynchronizers; } }); var crosshairsSynchronizers = { synchronizers: {} }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"debugReactivity.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/debugReactivity.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); Meteor.startup(function () { var debug = false; if (debug === true) { var logRenders = function () { Object.keys(Template).forEach(function (name) { if (name.indexOf('_') > -1) { return; } var template = Template[name]; var oldRender = template.rendered; var counter = 0; template.rendered = function () { console.log(name, 'render count: ', ++counter); oldRender && oldRender.apply(this, arguments); }; }); }; // http://www.meteorpedia.com/read/Debugging_Reactivity Meteor.autorun(function (computation) { computation.onInvalidate(function () { console.trace(); }); }); var wrappedFind = Meteor.Collection.prototype.find; Meteor.Collection.prototype.find = function () { var cursor = wrappedFind.apply(this, arguments); var collectionName = this._name || this._debugName; /*cursor.observeChanges({ added: function(id, fields) { console.log(collectionName, 'added', id, fields); }, changed: function(id, fields) { console.log(collectionName, 'changed', id, fields); }, movedBefore: function(id, before) { console.log(collectionName, 'movedBefore', id, before); }, removed: function(id) { console.log(collectionName, 'removed', id); } });*/ cursor.observe({ added: function (data) { console.log(collectionName, 'added', data); }, changed: function (data) { console.log(collectionName, 'changed', data); }, removed: function (data) { console.log(collectionName, 'removed', data); } }); return cursor; }; logRenders(); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"dialogUtils.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/dialogUtils.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ dialogUtils: function () { return dialogUtils; } }); var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 1); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 2); var setFocusToActiveViewport; module.watch(require("./setFocusToActiveViewport"), { setFocusToActiveViewport: function (v) { setFocusToActiveViewport = v; } }, 3); var doneCallbackFunction; /** * Removes the backdrop abd closes opened dialog * and focus to the active viewport. If a done callback is set, * it's called before * @param {Boolean} runCallback Indicate if callback function needs to be called. Default: true */ var closeHandler = function () { var runCallback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; // Check if callback function exists if (runCallback && typeof doneCallbackFunction === 'function') { doneCallbackFunction(); } // Hide the lesion dialog $('#confirmDeleteDialog').css('display', 'none'); // Remove the backdrop $('.removableBackdrop').remove(); // Remove the callback doneCallbackFunction = undefined; // Restore the focus to the active viewport setFocusToActiveViewport(); }; /** * Displays the confirmation dialog template and the removable backdrop element * * @param doneCallback A callback * @param options */ var showConfirmDialog = function (doneCallback, options) { // Show the backdrop options = options || {}; Blaze.renderWithData(Template.removableBackdrop, options, document.body); var confirmDeleteDialog = $('#confirmDeleteDialog'); confirmDeleteDialog.remove(); var viewer = document.getElementById('viewer'); Blaze.renderWithData(Template.confirmDeleteDialog, options, viewer); // Make sure the context menu is closed when the user clicks away $('.removableBackdrop').one('mousedown touchstart', function () { // Close dialog without calling callback closeHandler(false); }); confirmDeleteDialog = $('#confirmDeleteDialog'); confirmDeleteDialog.css('display', 'block'); confirmDeleteDialog.focus(); // If callback function is defined, save it for closeHandler if (doneCallback && typeof doneCallback === 'function') { doneCallbackFunction = doneCallback; } }; var dialogUtils = { showConfirmDialog: showConfirmDialog, closeHandler: closeHandler }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"displayReferenceLines.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/displayReferenceLines.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ displayReferenceLines: function () { return displayReferenceLines; } }); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); function displayReferenceLines(element) { // Check if image plane (orientation / loction) data is present for the current image var enabledElement = cornerstone.getEnabledElement(element); // Check if element is already enabled and it's image was rendered if (!enabledElement || !enabledElement.image) { OHIF.log.info('displayReferenceLines enabled element is undefined or it\'s image is not rendered'); return; } var imageId = enabledElement.image.imageId; var imagePlane = cornerstone.metaData.get('imagePlane', imageId); // Disable reference lines for the current element cornerstoneTools.referenceLines.tool.disable(element); if (!OHIF.viewer.refLinesEnabled || !imagePlane || !imagePlane.frameOfReferenceUID) { OHIF.log.info('displayReferenceLines refLinesEnabled is not enabled, no imagePlane or no frameOfReferenceUID'); return; } OHIF.log.info("displayReferenceLines for image with id: " + imageId); // Loop through all other viewport elements and enable reference lines $('.imageViewerViewport').not(element).each(function (index, viewportElement) { var imageId; if ($(viewportElement).find('canvas').length) { try { var _enabledElement = cornerstone.getEnabledElement(viewportElement); imageId = _enabledElement.image.imageId; } catch (error) { return; } if (!imageId) { return; } cornerstoneTools.referenceLines.tool.enable(viewportElement, OHIF.viewer.updateImageSynchronizer); } }); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"getElementIfNotEmpty.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/getElementIfNotEmpty.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ getElementIfNotEmpty: function () { return getElementIfNotEmpty; } }); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 0); function getElementIfNotEmpty(viewportIndex) { // Meteor template helpers run more often than expected // They often seem to run just before the whole template is rendered // This meant that the onRendered event hadn't fired yet, so the // element wasn't enabled / set empty yet. The check here // for canvases under the 'enabled' element div is to prevent // 'undefined' errors from the helper functions var imageViewerViewports = $('.imageViewerViewport'), element = imageViewerViewports.get(viewportIndex), canvases = imageViewerViewports.eq(viewportIndex).find('canvas'); if (!element || $(element).hasClass('empty') || canvases.length === 0) { return; } // Check to make sure the element is enabled. try { var enabledElement = cornerstone.getEnabledElement(element); } catch (error) { return; } return element; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"getFrameOfReferenceUID.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/getFrameOfReferenceUID.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ getFrameOfReferenceUID: function () { return getFrameOfReferenceUID; } }); function getFrameOfReferenceUID(element) { var enabledElement; try { enabledElement = cornerstone.getEnabledElement(element); } catch (error) { return; } if (!enabledElement || !enabledElement.image) { return; } var imageId = enabledElement.image.imageId; var imagePlane = cornerstone.metaData.get('imagePlane', imageId); if (!imagePlane || !imagePlane.frameOfReferenceUID) { return; } return imagePlane.frameOfReferenceUID; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"getImageId.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/getImageId.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ getImageId: function () { return getImageId; } }); var getWADORSImageId; module.watch(require("./getWADORSImageId"), { getWADORSImageId: function (v) { getWADORSImageId = v; } }, 0); // https://stackoverflow.com/a/6021027/3895126 function updateQueryStringParameter(uri, key, value) { var regex = new RegExp('([?&])' + key + '=.*?(&|$)', 'i'); var separator = uri.indexOf('?') !== -1 ? '&' : '?'; if (uri.match(regex)) { return uri.replace(regex, '$1' + key + '=' + value + '$2'); } else { return uri + separator + key + '=' + value; } } /** * Obtain an imageId for Cornerstone from an image instance * * @param instance * @param frame * @param thumbnail * @returns {string} The imageId to be used by Cornerstone */ function getImageId(instance, frame) { var thumbnail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (!instance) { return; } if (typeof instance.getImageId === 'function') { return instance.getImageId(); } if (instance.url) { if (frame !== undefined) { instance.url = updateQueryStringParameter(instance.url, 'frame', frame); } return instance.url; } var renderingAttr = thumbnail ? 'thumbnailRendering' : 'imageRendering'; if (!instance[renderingAttr] || instance[renderingAttr] === 'wadouri' || !instance.wadorsuri) { var imageId = 'dicomweb:' + instance.wadouri; if (frame !== undefined) { imageId += '&frame=' + frame; } return imageId; } else { return getWADORSImageId(instance, frame, thumbnail); // WADO-RS Retrieve Frame } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"getImageIdForImagePath.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/getImageIdForImagePath.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); module.export({ getImageIdForImagePath: function () { return getImageIdForImagePath; } }); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); var getImageIdForImagePath = function (imagePath) { var thumbnail = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var _imagePath$split = imagePath.split('_'), _imagePath$split2 = (0, _slicedToArray2.default)(_imagePath$split, 4), studyInstanceUid = _imagePath$split2[0], seriesInstanceUid = _imagePath$split2[1], sopInstanceUid = _imagePath$split2[2], frameIndex = _imagePath$split2[3]; var study = OHIF.viewer.Studies.findBy({ studyInstanceUid: studyInstanceUid }); var studyMetadata = OHIF.viewerbase.getStudyMetadata(study); var series = studyMetadata.getSeriesByUID(seriesInstanceUid); var instance = series.getInstanceByUID(sopInstanceUid); var imageId = OHIF.viewerbase.getImageId(instance, frameIndex, thumbnail); return imageId; }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"getStackDataIfNotEmpty.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/getStackDataIfNotEmpty.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ getStackDataIfNotEmpty: function () { return getStackDataIfNotEmpty; } }); var getElementIfNotEmpty; module.watch(require("./getElementIfNotEmpty.js"), { getElementIfNotEmpty: function (v) { getElementIfNotEmpty = v; } }, 0); function getStackDataIfNotEmpty(viewportIndex) { var element = getElementIfNotEmpty(viewportIndex); if (!element) { return; } var stackToolData = cornerstoneTools.getToolState(element, 'stack'); if (!stackToolData || !stackToolData.data || !stackToolData.data.length) { return; } var stack = stackToolData.data[0]; if (!stack) { return; } return stack; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"getStudyMetadata.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/getStudyMetadata.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ getStudyMetadata: function () { return getStudyMetadata; } }); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); var getStudyMetadata = function (study) { var studyMetadata = study; if (study && !(studyMetadata instanceof OHIF.viewerbase.metadata.StudyMetadata)) { studyMetadata = new OHIF.metadata.StudyMetadata(study, study.studyInstanceUid); } return studyMetadata; }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"getWADORSImageId.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/getWADORSImageId.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ getWADORSImageId: function () { return getWADORSImageId; } }); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); var getWADORSImageUrl; module.watch(require("./getWADORSImageUrl"), { getWADORSImageUrl: function (v) { getWADORSImageUrl = v; } }, 1); function getWADORSImageId(instance, frame) { var uri = getWADORSImageUrl(instance, frame); if (!uri) { return; } var imageId = "wadors:" + uri; OHIF.log.info('WADO-RS ImageID: ' + imageId); return imageId; } ; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"getWADORSImageUrl.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/getWADORSImageUrl.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ getWADORSImageUrl: function () { return getWADORSImageUrl; } }); function getWADORSImageUrl(instance, frame) { var wadorsuri = instance.wadorsuri; if (!wadorsuri) { return; } // We need to sum 1 because WADO-RS frame number is 1-based frame = (frame || 0) + 1; // Replaces /frame/1 by /frame/{frame} wadorsuri = wadorsuri.replace(/(%2Fframes%2F)(\d+)/, "$1" + frame); return wadorsuri; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"hotkeyUtils.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/hotkeyUtils.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ hotkeyUtils: function () { return hotkeyUtils; } }); var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 1); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 2); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 3); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 4); var toolManager; module.watch(require("./toolManager"), { toolManager: function (v) { toolManager = v; } }, 5); var switchToImageRelative; module.watch(require("./switchToImageRelative"), { switchToImageRelative: function (v) { switchToImageRelative = v; } }, 6); var switchToImageByIndex; module.watch(require("./switchToImageByIndex"), { switchToImageByIndex: function (v) { switchToImageByIndex = v; } }, 7); var viewportUtils; module.watch(require("./viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 8); var panelNavigation; module.watch(require("./panelNavigation"), { panelNavigation: function (v) { panelNavigation = v; } }, 9); var WLPresets; module.watch(require("./WLPresets"), { WLPresets: function (v) { WLPresets = v; } }, 10); // TODO: add this to namespace definitions Meteor.startup(function () { OHIF.viewer.loadIndicatorDelay = 200; OHIF.viewer.defaultTool = 'wwwc'; OHIF.viewer.refLinesEnabled = true; OHIF.viewer.isPlaying = {}; OHIF.viewer.cine = { framesPerSecond: 24, loop: true }; OHIF.viewer.defaultHotkeys = { // Tool hotkeys defaultTool: 'ESC', zoom: 'Z', wwwc: 'W', pan: 'P', angle: 'A', stackScroll: 'S', magnify: 'M', length: '', annotate: '', dragProbe: '', ellipticalRoi: '', rectangleRoi: '', // Viewport hotkeys flipH: 'H', flipV: 'V', rotateR: 'R', rotateL: 'L', invert: 'I', zoomIn: '', zoomOut: '', zoomToFit: '', resetViewport: '', clearTools: '', // Viewport navigation hotkeys scrollDown: 'DOWN', scrollUp: 'UP', scrollLastImage: 'END', scrollFirstImage: 'HOME', previousDisplaySet: 'PAGEUP', nextDisplaySet: 'PAGEDOWN', nextPanel: 'RIGHT', previousPanel: 'LEFT', // Miscellaneous hotkeys toggleOverlayTags: 'O', toggleCinePlay: 'SPACE', toggleCineDialog: '', toggleDownloadDialog: '', // Preset hotkeys WLPreset0: '1', WLPreset1: '2', WLPreset2: '3', WLPreset3: '4', WLPreset4: '5', WLPreset5: '6', WLPreset6: '7', WLPreset7: '8', WLPreset8: '9', WLPreset9: '0' }; // For now OHIF.viewer.hotkeys = OHIF.viewer.defaultHotkeys; // Create commands context for viewer var contextName = 'viewer'; OHIF.commands.createContext(contextName); // Create a function that returns true if the active viewport is empty var isActiveViewportEmpty = function () { var activeViewport = Session.get('activeViewport') || 0; return $('.imageViewerViewport').eq(activeViewport).hasClass('empty'); }; // Functions to register the tool switching commands var registerToolCommands = function (map) { return _.each(map, function (commandName, toolId) { OHIF.commands.register(contextName, toolId, { name: commandName, action: toolManager.setActiveTool, params: toolId }); }); }; // Register the default tool command OHIF.commands.register(contextName, 'defaultTool', { name: 'Default Tool', action: function () { return toolManager.setActiveTool(toolManager.getDefaultTool()); } }); // Register the tool switching commands registerToolCommands({ wwwc: 'W/L', zoom: 'Zoom', angle: 'Angle Measurement', dragProbe: 'Pixel Probe', ellipticalRoi: 'Elliptical ROI', rectangleRoi: 'Rectangle ROI', magnify: 'Magnify', annotate: 'Annotate', stackScroll: 'Scroll Stack', pan: 'Pan', length: 'Length Measurement', wwwcRegion: 'W/L by Region', crosshairs: 'Crosshairs' }); // Functions to register the viewport commands var registerViewportCommands = function (map) { return _.each(map, function (commandName, commandId) { OHIF.commands.register(contextName, commandId, { name: commandName, action: viewportUtils[commandId], disabled: isActiveViewportEmpty }); }); }; // Register the viewport commands registerViewportCommands({ zoomIn: 'Zoom In', zoomOut: 'Zoom Out', zoomToFit: 'Zoom to Fit', invert: 'Invert', flipH: 'Flip Horizontally', flipV: 'Flip Vertically', rotateR: 'Rotate Right', rotateL: 'Rotate Left', resetViewport: 'Reset', clearTools: 'Clear Tools' }); // Register the preset switching commands var applyPreset = function (presetName) { return WLPresets.applyWLPresetToActiveElement(presetName); }; for (var i = 0; i < 10; i++) { OHIF.commands.register(contextName, "WLPreset" + i, { name: "W/L Preset " + (i + 1), action: applyPreset, params: i }); } // Check if display sets can be moved var canMoveDisplaySets = function (isNext) { if (!OHIF.viewerbase.layoutManager) { return false; } else { return OHIF.viewerbase.layoutManager.canMoveDisplaySets(isNext); } }; // Register viewport navigation commands OHIF.commands.set(contextName, { scrollDown: { name: 'Scroll Down', action: function () { return !isActiveViewportEmpty() && switchToImageRelative(1); } }, scrollUp: { name: 'Scroll Up', action: function () { return !isActiveViewportEmpty() && switchToImageRelative(-1); } }, scrollFirstImage: { name: 'Scroll to First Image', action: function () { return !isActiveViewportEmpty() && switchToImageByIndex(0); } }, scrollLastImage: { name: 'Scroll to Last Image', action: function () { return !isActiveViewportEmpty() && switchToImageByIndex(-1); } }, previousDisplaySet: { name: 'Previous Series', action: function () { return OHIF.viewerbase.layoutManager.moveDisplaySets(false); }, disabled: function () { return !canMoveDisplaySets(false); } }, nextDisplaySet: { name: 'Next Series', action: function () { return OHIF.viewerbase.layoutManager.moveDisplaySets(true); }, disabled: function () { return !canMoveDisplaySets(true); } }, nextPanel: { name: 'Next Panel', action: function () { return panelNavigation.loadNextActivePanel(); } }, previousPanel: { name: 'Previous Panel', action: function () { return panelNavigation.loadPreviousActivePanel(); } } }, true); // Register miscellaneous commands OHIF.commands.set(contextName, { toggleOverlayTags: { name: 'Toggle Image Info Overlay', action: function () { var $dicomTags = $('.imageViewerViewportOverlay .dicomTag'); $dicomTags.toggle($dicomTags.eq(0).css('display') === 'none'); } }, toggleCinePlay: { name: 'Play/Pause Cine', action: viewportUtils.toggleCinePlay, disabled: OHIF.viewerbase.viewportUtils.hasMultipleFrames }, toggleCineDialog: { name: 'Show/Hide Cine Controls', action: viewportUtils.toggleCineDialog, disabled: OHIF.viewerbase.viewportUtils.hasMultipleFrames }, toggleDownloadDialog: { name: 'Show/Hide Download Dialog', action: viewportUtils.toggleDownloadDialog, disabled: function () { return !viewportUtils.isDownloadEnabled(); } } }, true); OHIF.viewer.hotkeyFunctions = {}; OHIF.viewer.loadedSeriesData = {}; // Enable hotkeys hotkeyUtils.enableHotkeys(); }); // Define a jQuery reverse function $.fn.reverse = [].reverse; /** * Overrides OHIF's refLinesEnabled * @param {Boolean} refLinesEnabled True to enable and False to disable */ function setOHIFRefLines(refLinesEnabled) { OHIF.viewer.refLinesEnabled = refLinesEnabled; } /** * Overrides OHIF's hotkeys * @param {Object} hotkeys Object with hotkeys mapping */ function setOHIFHotkeys(hotkeys) { OHIF.viewer.hotkeys = hotkeys; } /** * Binds all hotkeys keydown events to the tasks defined in * OHIF.viewer.hotkeys or a given param * @param {Object} hotkeys hotkey and task mapping (not required). If not given, uses OHIF.viewer.hotkeys */ function enableHotkeys(hotkeys) { var definitions = hotkeys || OHIF.viewer.hotkeys; OHIF.hotkeys.set('viewer', definitions, true); OHIF.context.set('viewer'); } /** * Export functions inside hotkeyUtils namespace. */ var hotkeyUtils = { setOHIFRefLines: setOHIFRefLines, /* @TODO: find a better place for this... */ setOHIFHotkeys: setOHIFHotkeys, enableHotkeys: enableHotkeys }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"imageViewerViewportData.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/imageViewerViewportData.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ imageViewerViewportData: function () { return imageViewerViewportData; } }); var imageViewerViewportData = { callbacks: {}, extendData: function () {// No-Op function... } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"instanceClassSpecificViewport.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/instanceClassSpecificViewport.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ getInstanceClassDefaultViewport: function () { return getInstanceClassDefaultViewport; }, setInstanceClassDefaultViewportFunction: function () { return setInstanceClassDefaultViewportFunction; } }); var instanceClassViewportSettingsFunctions = {}; var getInstanceClassDefaultViewport = function (series, enabledElement, imageId) { var instanceClass = series.sopClassUid; if (!instanceClassViewportSettingsFunctions[instanceClass]) { return; } return instanceClassViewportSettingsFunctions[instanceClass](series, enabledElement, imageId); }; var setInstanceClassDefaultViewportFunction = function (instanceClass, fn) { instanceClassViewportSettingsFunctions[instanceClass] = fn; }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"isImage.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/isImage.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ isImage: function () { return isImage; } }); var sopClassDictionary; module.watch(require("./sopClassDictionary"), { sopClassDictionary: function (v) { sopClassDictionary = v; } }, 0); function isImage(sopClassUid) { if (sopClassUid === sopClassDictionary.ComputedRadiographyImageStorage || sopClassUid === sopClassDictionary.DigitalXRayImageStorageForPresentation || sopClassUid === sopClassDictionary.DigitalXRayImageStorageForProcessing || sopClassUid === sopClassDictionary.DigitalMammographyXRayImageStorageForPresentation || sopClassUid === sopClassDictionary.DigitalMammographyXRayImageStorageForProcessing || sopClassUid === sopClassDictionary.DigitalIntraOralXRayImageStorageForPresentation || sopClassUid === sopClassDictionary.DigitalIntraOralXRayImageStorageForProcessing || sopClassUid === sopClassDictionary.CTImageStorage || sopClassUid === sopClassDictionary.EnhancedCTImageStorage || sopClassUid === sopClassDictionary.LegacyConvertedEnhancedCTImageStorage || sopClassUid === sopClassDictionary.UltrasoundMultiframeImageStorage || sopClassUid === sopClassDictionary.MRImageStorage || sopClassUid === sopClassDictionary.EnhancedMRImageStorage || sopClassUid === sopClassDictionary.EnhancedMRColorImageStorage || sopClassUid === sopClassDictionary.LegacyConvertedEnhancedMRImageStorage || sopClassUid === sopClassDictionary.UltrasoundImageStorage || sopClassUid === sopClassDictionary.SecondaryCaptureImageStorage || sopClassUid === sopClassDictionary.MultiframeSingleBitSecondaryCaptureImageStorage || sopClassUid === sopClassDictionary.MultiframeGrayscaleByteSecondaryCaptureImageStorage || sopClassUid === sopClassDictionary.MultiframeGrayscaleWordSecondaryCaptureImageStorage || sopClassUid === sopClassDictionary.MultiframeTrueColorSecondaryCaptureImageStorage || sopClassUid === sopClassDictionary.XRayAngiographicImageStorage || sopClassUid === sopClassDictionary.EnhancedXAImageStorage || sopClassUid === sopClassDictionary.XRayRadiofluoroscopicImageStorage || sopClassUid === sopClassDictionary.EnhancedXRFImageStorage || sopClassUid === sopClassDictionary.XRay3DAngiographicImageStorage || sopClassUid === sopClassDictionary.XRay3DCraniofacialImageStorage || sopClassUid === sopClassDictionary.BreastTomosynthesisImageStorage || sopClassUid === sopClassDictionary.BreastProjectionXRayImageStorageForPresentation || sopClassUid === sopClassDictionary.BreastProjectionXRayImageStorageForProcessing || sopClassUid === sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation || sopClassUid === sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForProcessing || sopClassUid === sopClassDictionary.NuclearMedicineImageStorage || sopClassUid === sopClassDictionary.VLEndoscopicImageStorage || sopClassUid === sopClassDictionary.VideoEndoscopicImageStorage || sopClassUid === sopClassDictionary.VLMicroscopicImageStorage || sopClassUid === sopClassDictionary.VideoMicroscopicImageStorage || sopClassUid === sopClassDictionary.VLSlideCoordinatesMicroscopicImageStorage || sopClassUid === sopClassDictionary.VLPhotographicImageStorage || sopClassUid === sopClassDictionary.VideoPhotographicImageStorage || sopClassUid === sopClassDictionary.OphthalmicPhotography8BitImageStorage || sopClassUid === sopClassDictionary.OphthalmicPhotography16BitImageStorage || sopClassUid === sopClassDictionary.OphthalmicTomographyImageStorage || sopClassUid === sopClassDictionary.VLWholeSlideMicroscopyImageStorage || sopClassUid === sopClassDictionary.PositronEmissionTomographyImageStorage || sopClassUid === sopClassDictionary.EnhancedPETImageStorage || sopClassUid === sopClassDictionary.LegacyConvertedEnhancedPETImageStorage || sopClassUid === sopClassDictionary.RTImageStorage) { return true; } return false; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"panelNavigation.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/panelNavigation.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ panelNavigation: function () { return panelNavigation; } }); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 0); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 1); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 2); var setActiveViewport; module.watch(require("./setActiveViewport"), { setActiveViewport: function (v) { setActiveViewport = v; } }, 3); var loadPreviousActivePanel = function () { OHIF.log.info('nextActivePanel'); var currentIndex = Session.get('activeViewport'); currentIndex--; var $viewports = $('.viewportContainer'); var numViewports = $viewports.length; if (currentIndex < 0) { currentIndex = numViewports - 1; } var viewportContainer = $viewports.get(currentIndex); if (!viewportContainer) { return; } setActiveViewport(viewportContainer); }; var loadNextActivePanel = function () { OHIF.log.info('nextActivePanel'); var currentIndex = Session.get('activeViewport'); currentIndex++; var $viewports = $('.viewportContainer'); var numViewports = $viewports.length; if (currentIndex >= numViewports) { currentIndex = 0; } var viewportContainer = $viewports.get(currentIndex); if (!viewportContainer) { return; } setActiveViewport(viewportContainer); }; /** * Export functions inside panelNavigation namespace. */ var panelNavigation = { loadPreviousActivePanel: loadPreviousActivePanel, loadNextActivePanel: loadNextActivePanel }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"prepareViewerData.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/prepareViewerData.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ prepareViewerData: function () { return prepareViewerData; } }); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 0); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 1); var prepareViewerData = function (_ref) { var studyInstanceUids = _ref.studyInstanceUids, seriesInstanceUids = _ref.seriesInstanceUids, timepointId = _ref.timepointId, _ref$timepointsFilter = _ref.timepointsFilter, timepointsFilter = _ref$timepointsFilter === void 0 ? {} : _ref$timepointsFilter; // Clear the cornerstone tool data to sync the measurements with the measurements API cornerstoneTools.globalImageIdSpecificToolStateManager.restoreToolState({}); // Retrieve the studies metadata var promise = new Promise(function (resolve, reject) { var processData = function (viewerData) { OHIF.studies.retrieveStudiesMetadata(viewerData.studyInstanceUids, viewerData.seriesInstanceUids).then(function (studies) { // Add additional metadata to our study from the studylist studies.forEach(function (study) { var studylistStudy = OHIF.studylist.collections.Studies.findOne({ studyInstanceUid: study.studyInstanceUid }); if (!studylistStudy) { return; } Object.assign(study, studylistStudy); }); resolve({ studies: studies, viewerData: viewerData }); }).catch(reject); }; // Check if the studies are already given and ignore the timepoint ID if so if (studyInstanceUids && studyInstanceUids.length) { var viewerData = { studyInstanceUids: studyInstanceUids, seriesInstanceUids: seriesInstanceUids }; processData(viewerData); } else { // Find the timepoint by ID and load the studies from it OHIF.studylist.timepointApi.retrieveTimepoints(timepointsFilter).then(function () { var viewerData = buildViewerDataFromTimepointId(timepointId); processData(viewerData); }).catch(reject); } }); return promise; }; var buildViewerDataFromTimepointId = function (timepointId) { var timepoint = OHIF.studylist.timepointApi.timepoints.findOne({ timepointId: timepointId }); if (!timepoint) { throw new Error('Unable to find a time point with the given ID'); } // Get the relevant studyInstanceUids given the timepoints var data = getDataFromTimepoint(timepoint); if (!data.studyInstanceUids) { throw new Error('No studies found that are related to this timepoint'); } // Build the viewer data and return it return Object.assign(data, { currentTimepointId: timepointId }); }; /** * Retrieves related studies given a Baseline or Follow-up Timepoint * * @param {Object} timepoint A document from the Timepoints Collection * @returns {Object} An object containing the related studies UIDs and timepoint IDs */ var getDataFromTimepoint = function (timepoint) { var relatedStudies = _.clone(timepoint.studyInstanceUids); // If this is the baseline, we should stop here and return the relevant studies if (isBaseline(timepoint)) { return { studyInstanceUids: relatedStudies, timepointIds: [timepoint.timepointId] }; } // Otherwise, this is a follow-up exam, so we should also find the baseline timepoint, // and all studies related to it. We also enforce that the Baseline should have a studyDate // prior to the latest studyDate in the current (Follow-up) Timepoint. var Timepoints = OHIF.studylist.timepointApi.timepoints; var baseline = Timepoints.findOne({ timepointType: 'baseline', patientId: timepoint.patientId, latestDate: { $lte: timepoint.latestDate } }); var timepointIds = []; if (baseline) { relatedStudies = relatedStudies.concat(baseline.studyInstanceUids); timepointIds.push(baseline.timepointId); } else { OHIF.log.warn('No Baseline found while opening a Follow-up Timepoint'); } var priorFilter = { latestDate: { $lt: timepoint.latestDate } }; var priorSorting = { sort: { latestDate: -1 } }; var prior = OHIF.studylist.timepointApi.timepoints.findOne(priorFilter, priorSorting); if (prior && prior.timepointId !== baseline.timepointId) { relatedStudies = relatedStudies.concat(prior.studyInstanceUids); timepointIds.push(prior.timepointId); } relatedStudies = _.uniq(relatedStudies); timepointIds.push(timepoint.timepointId); return { studyInstanceUids: relatedStudies, timepointIds: timepointIds }; }; /** * Checks if a Timepoints is a baseline or not * * @param {Object} timepoint A document from the Timepoints Collection * @returns {boolean} Whether or not the timepoint is stored as a Baseline */ var isBaseline = function (timepoint) { return timepoint.timepointType === 'baseline'; }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"renderViewer.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/renderViewer.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ renderViewer: function () { return renderViewer; } }); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); var renderViewer = function (context, params) { var layoutTemplate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'app'; // Wait until the viewer data is ready to render it var promise = OHIF.viewerbase.prepareViewerData(params); // Show loading state while preparing the viewer data OHIF.ui.showDialog('dialogLoading', { promise: promise }); // Render the viewer when the data is ready promise.then(function (_ref) { var studies = _ref.studies, viewerData = _ref.viewerData; OHIF.viewer.data = viewerData; context.render(layoutTemplate, { data: { template: 'viewer', studies: studies } }); }).catch(function (error) { context.render(layoutTemplate, { data: { template: 'errorText', error: error } }); }); }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"setActiveViewport.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/setActiveViewport.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ setActiveViewport: function () { return setActiveViewport; } }); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 0); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 1); var Random; module.watch(require("meteor/random"), { Random: function (v) { Random = v; } }, 2); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 3); var StudyPrefetcher; module.watch(require("./classes/StudyPrefetcher"), { StudyPrefetcher: function (v) { StudyPrefetcher = v; } }, 4); var displayReferenceLines; module.watch(require("./displayReferenceLines"), { displayReferenceLines: function (v) { displayReferenceLines = v; } }, 5); var PLUGIN_CORNERSTONE = 'cornerstone'; /** * Sets a viewport element active * @param {node} element DOM element to be activated or viewportIndex */ function setActiveViewport(element) { var $viewports = $('.viewportContainer'); var viewportIndex = $viewports.index(element); var $element = $viewports.eq(viewportIndex); if (!$element.length) { OHIF.log.info('setActiveViewport element does not exist'); return; } OHIF.log.info("setActiveViewport setting viewport index: " + viewportIndex); // If viewport is not active if (!$element.parents('.viewportContainer').hasClass('active')) { // Trigger an event for compatibility with other systems $element.trigger('OHIFBeforeActivateViewport'); } // When an OHIFActivateViewport event is fired, update the Meteor Session // with the viewport index that it was fired from. Session.set('activeViewport', viewportIndex); // Finally, enable stack prefetching and hide the reference lines from // the newly activated viewport that has a canvas var layoutManager = OHIF.viewerbase.layoutManager; var viewportData = layoutManager.viewportData[viewportIndex]; if (viewportData.plugin === PLUGIN_CORNERSTONE && $element.find('canvas').length) { // Cornerstone Tools compare DOM elements (check getEnabledElement cornerstone function) // so we can't pass a jQuery object as an argument, otherwise it throws an excepetion var domElement = $element.find('.imageViewerViewport').get(0); displayReferenceLines(domElement); StudyPrefetcher.getInstance().prefetch(); // @TODO Add this to OHIFAfterActivateViewport handler... var synchronizer = OHIF.viewer.stackImagePositionOffsetSynchronizer; if (!synchronizer) { return; } synchronizer.update(); } // Set the div to focused, so keypress events are handled //$(element).focus(); //.focus() event breaks in FF&IE $element.triggerHandler('focus'); // Trigger OHIFAfterActivateViewport event on activated instance // for compatibility with other systems $element.trigger('OHIFAfterActivateViewport'); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"setFocusToActiveViewport.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/setFocusToActiveViewport.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ setFocusToActiveViewport: function () { return setFocusToActiveViewport; } }); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 0); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 1); /** * Restores the browser focus to the currently specified active viewport * as determined from Meteor's Session variable. * * This is allows keydown events to be captured on the focused element. */ var setFocusToActiveViewport = function () { // Get the list of viewports var viewports = $('.imageViewerViewport'); // Get the current active viewport index from Session var activeViewportIndex = Session.get('activeViewport'); // Find the div from the list of viewports var activeViewport = viewports.eq(activeViewportIndex); // Set the browser focus to this div activeViewport.focus(); }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"sopClassDictionary.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/sopClassDictionary.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ sopClassDictionary: function () { return sopClassDictionary; } }); var sopClassDictionary = { ComputedRadiographyImageStorage: "1.2.840.10008.5.1.4.1.1.1", DigitalXRayImageStorageForPresentation: "1.2.840.10008.5.1.4.1.1.1.1", DigitalXRayImageStorageForProcessing: "1.2.840.10008.5.1.4.1.1.1.1.1", DigitalMammographyXRayImageStorageForPresentation: "1.2.840.10008.5.1.4.1.1.1.2", DigitalMammographyXRayImageStorageForProcessing: "1.2.840.10008.5.1.4.1.1.1.2.1", DigitalIntraOralXRayImageStorageForPresentation: "1.2.840.10008.5.1.4.1.1.1.3", DigitalIntraOralXRayImageStorageForProcessing: "1.2.840.10008.5.1.4.1.1.1.3.1", CTImageStorage: "1.2.840.10008.5.1.4.1.1.2", EnhancedCTImageStorage: "1.2.840.10008.5.1.4.1.1.2.1", LegacyConvertedEnhancedCTImageStorage: "1.2.840.10008.5.1.4.1.1.2.2", UltrasoundMultiframeImageStorage: "1.2.840.10008.5.1.4.1.1.3.1", MRImageStorage: "1.2.840.10008.5.1.4.1.1.4", EnhancedMRImageStorage: "1.2.840.10008.5.1.4.1.1.4.1", MRSpectroscopyStorage: "1.2.840.10008.5.1.4.1.1.4.2", EnhancedMRColorImageStorage: "1.2.840.10008.5.1.4.1.1.4.3", LegacyConvertedEnhancedMRImageStorage: "1.2.840.10008.5.1.4.1.1.4.4", UltrasoundImageStorage: "1.2.840.10008.5.1.4.1.1.6.1", EnhancedUSVolumeStorage: "1.2.840.10008.5.1.4.1.1.6.2", SecondaryCaptureImageStorage: "1.2.840.10008.5.1.4.1.1.7", MultiframeSingleBitSecondaryCaptureImageStorage: "1.2.840.10008.5.1.4.1.1.7.1", MultiframeGrayscaleByteSecondaryCaptureImageStorage: "1.2.840.10008.5.1.4.1.1.7.2", MultiframeGrayscaleWordSecondaryCaptureImageStorage: "1.2.840.10008.5.1.4.1.1.7.3", MultiframeTrueColorSecondaryCaptureImageStorage: "1.2.840.10008.5.1.4.1.1.7.4", Sop12LeadECGWaveformStorage: "1.2.840.10008.5.1.4.1.1.9.1.1", GeneralECGWaveformStorage: "1.2.840.10008.5.1.4.1.1.9.1.2", AmbulatoryECGWaveformStorage: "1.2.840.10008.5.1.4.1.1.9.1.3", HemodynamicWaveformStorage: "1.2.840.10008.5.1.4.1.1.9.2.1", CardiacElectrophysiologyWaveformStorage: "1.2.840.10008.5.1.4.1.1.9.3.1", BasicVoiceAudioWaveformStorage: "1.2.840.10008.5.1.4.1.1.9.4.1", GeneralAudioWaveformStorage: "1.2.840.10008.5.1.4.1.1.9.4.2", ArterialPulseWaveformStorage: "1.2.840.10008.5.1.4.1.1.9.5.1", RespiratoryWaveformStorage: "1.2.840.10008.5.1.4.1.1.9.6.1", GrayscaleSoftcopyPresentationStateStorage: "1.2.840.10008.5.1.4.1.1.11.1", ColorSoftcopyPresentationStateStorage: "1.2.840.10008.5.1.4.1.1.11.2", PseudoColorSoftcopyPresentationStateStorage: "1.2.840.10008.5.1.4.1.1.11.3", BlendingSoftcopyPresentationStateStorage: "1.2.840.10008.5.1.4.1.1.11.4", XAXRFGrayscaleSoftcopyPresentationStateStorage: "1.2.840.10008.5.1.4.1.1.11.5", XRayAngiographicImageStorage: "1.2.840.10008.5.1.4.1.1.12.1", EnhancedXAImageStorage: "1.2.840.10008.5.1.4.1.1.12.1.1", XRayRadiofluoroscopicImageStorage: "1.2.840.10008.5.1.4.1.1.12.2", EnhancedXRFImageStorage: "1.2.840.10008.5.1.4.1.1.12.2.1", XRay3DAngiographicImageStorage: "1.2.840.10008.5.1.4.1.1.13.1.1", XRay3DCraniofacialImageStorage: "1.2.840.10008.5.1.4.1.1.13.1.2", BreastTomosynthesisImageStorage: "1.2.840.10008.5.1.4.1.1.13.1.3", BreastProjectionXRayImageStorageForPresentation: "1.2.840.10008.5.1.4.1.1.13.1.4", BreastProjectionXRayImageStorageForProcessing: "1.2.840.10008.5.1.4.1.1.13.1.5", IntravascularOpticalCoherenceTomographyImageStorageForPresentation: "1.2.840.10008.5.1.4.1.1.14.1", IntravascularOpticalCoherenceTomographyImageStorageForProcessing: "1.2.840.10008.5.1.4.1.1.14.2", NuclearMedicineImageStorage: "1.2.840.10008.5.1.4.1.1.20", RawDataStorage: "1.2.840.10008.5.1.4.1.1.66", SpatialRegistrationStorage: "1.2.840.10008.5.1.4.1.1.66.1", SpatialFiducialsStorage: "1.2.840.10008.5.1.4.1.1.66.2", DeformableSpatialRegistrationStorage: "1.2.840.10008.5.1.4.1.1.66.3", SegmentationStorage: "1.2.840.10008.5.1.4.1.1.66.4", SurfaceSegmentationStorage: "1.2.840.10008.5.1.4.1.1.66.5", RealWorldValueMappingStorage: "1.2.840.10008.5.1.4.1.1.67", SurfaceScanMeshStorage: "1.2.840.10008.5.1.4.1.1.68.1", SurfaceScanPointCloudStorage: "1.2.840.10008.5.1.4.1.1.68.2", VLEndoscopicImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.1", VideoEndoscopicImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.1.1", VLMicroscopicImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.2", VideoMicroscopicImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.2.1", VLSlideCoordinatesMicroscopicImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.3", VLPhotographicImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.4", VideoPhotographicImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.4.1", OphthalmicPhotography8BitImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.5.1", OphthalmicPhotography16BitImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.5.2", StereometricRelationshipStorage: "1.2.840.10008.5.1.4.1.1.77.1.5.3", OphthalmicTomographyImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.5.4", VLWholeSlideMicroscopyImageStorage: "1.2.840.10008.5.1.4.1.1.77.1.6", LensometryMeasurementsStorage: "1.2.840.10008.5.1.4.1.1.78.1", AutorefractionMeasurementsStorage: "1.2.840.10008.5.1.4.1.1.78.2", KeratometryMeasurementsStorage: "1.2.840.10008.5.1.4.1.1.78.3", SubjectiveRefractionMeasurementsStorage: "1.2.840.10008.5.1.4.1.1.78.4", VisualAcuityMeasurementsStorage: "1.2.840.10008.5.1.4.1.1.78.5", SpectaclePrescriptionReportStorage: "1.2.840.10008.5.1.4.1.1.78.6", OphthalmicAxialMeasurementsStorage: "1.2.840.10008.5.1.4.1.1.78.7", IntraocularLensCalculationsStorage: "1.2.840.10008.5.1.4.1.1.78.8", MacularGridThicknessandVolumeReport: "1.2.840.10008.5.1.4.1.1.79.1", OphthalmicVisualFieldStaticPerimetryMeasurementsStorage: "1.2.840.10008.5.1.4.1.1.80.1", OphthalmicThicknessMapStorage: "1.2.840.10008.5.1.4.1.1.81.1", CornealTopographyMapStorage: "1.2.840.10008.5.1.4.1.1.82.1", BasicTextSR: "1.2.840.10008.5.1.4.1.1.88.11", EnhancedSR: "1.2.840.10008.5.1.4.1.1.88.22", ComprehensiveSR: "1.2.840.10008.5.1.4.1.1.88.33", Comprehensive3DSR: "1.2.840.10008.5.1.4.1.1.88.34", ProcedureLog: "1.2.840.10008.5.1.4.1.1.88.40", MammographyCADSR: "1.2.840.10008.5.1.4.1.1.88.50", KeyObjectSelection: "1.2.840.10008.5.1.4.1.1.88.59", ChestCADSR: "1.2.840.10008.5.1.4.1.1.88.65", XRayRadiationDoseSR: "1.2.840.10008.5.1.4.1.1.88.67", RadiopharmaceuticalRadiationDoseSR: "1.2.840.10008.5.1.4.1.1.88.68", ColonCADSR: "1.2.840.10008.5.1.4.1.1.88.69", ImplantationPlanSRDocumentStorage: "1.2.840.10008.5.1.4.1.1.88.70", EncapsulatedPDFStorage: "1.2.840.10008.5.1.4.1.1.104.1", EncapsulatedCDAStorage: "1.2.840.10008.5.1.4.1.1.104.2", PositronEmissionTomographyImageStorage: "1.2.840.10008.5.1.4.1.1.128", EnhancedPETImageStorage: "1.2.840.10008.5.1.4.1.1.130", LegacyConvertedEnhancedPETImageStorage: "1.2.840.10008.5.1.4.1.1.128.1", BasicStructuredDisplayStorage: "1.2.840.10008.5.1.4.1.1.131", RTImageStorage: "1.2.840.10008.5.1.4.1.1.481.1", RTDoseStorage: "1.2.840.10008.5.1.4.1.1.481.2", RTStructureSetStorage: "1.2.840.10008.5.1.4.1.1.481.3", RTBeamsTreatmentRecordStorage: "1.2.840.10008.5.1.4.1.1.481.4", RTPlanStorage: "1.2.840.10008.5.1.4.1.1.481.5", RTBrachyTreatmentRecordStorage: "1.2.840.10008.5.1.4.1.1.481.6", RTTreatmentSummaryRecordStorage: "1.2.840.10008.5.1.4.1.1.481.7", RTIonPlanStorage: "1.2.840.10008.5.1.4.1.1.481.8", RTIonBeamsTreatmentRecordStorage: "1.2.840.10008.5.1.4.1.1.481.9", RTBeamsDeliveryInstructionStorage: "1.2.840.10008.5.1.4.34.7", GenericImplantTemplateStorage: "1.2.840.10008.5.1.4.43.1", ImplantAssemblyTemplateStorage: "1.2.840.10008.5.1.4.44.1", ImplantTemplateGroupStorage: "1.2.840.10008.5.1.4.45.1" }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"sortStudy.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/sortStudy.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ sortStudy: function () { return sortStudy; } }); var OHIFError; module.watch(require("./classes/OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 0); function sortStudy(study) { if (!study || !study.seriesList) { throw new OHIFError('Insufficient study data was provided to sortStudy'); } study.seriesList.sort(function (a, b) { return a.seriesNumber - b.seriesNumber; }); study.seriesList.forEach(function (series) { series.instances.sort(function (a, b) { return a.instanceNumber - b.instanceNumber; }); }); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"sortingManager.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/sortingManager.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ sortingManager: function () { return sortingManager; } }); var createStacks; module.watch(require("./createStacks"), { createStacks: function (v) { createStacks = v; } }, 0); var getDisplaySets = function (studyMetadata, seriesNumber, iteratorFunction) { var iteratorFn = typeof iteratorFunction !== 'function' ? createStacks : iteratorFunction; return iteratorFn(studyMetadata, seriesNumber); }; var sortingManager = { getDisplaySets: getDisplaySets }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"switchToImageByIndex.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/switchToImageByIndex.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ switchToImageByIndex: function () { return switchToImageByIndex; } }); var viewportUtils; module.watch(require("./viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 0); function switchToImageByIndex(newImageIdIndex) { var element = viewportUtils.getActiveViewportElement(); cornerstoneTools.scrollToIndex(element, newImageIdIndex); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"switchToImageRelative.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/switchToImageRelative.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ switchToImageRelative: function () { return switchToImageRelative; } }); var viewportUtils; module.watch(require("./viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 0); function switchToImageRelative(distanceFromCurrentIndex) { var element = viewportUtils.getActiveViewportElement(); cornerstoneTools.scroll(element, distanceFromCurrentIndex); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"textMarkerUtils.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/textMarkerUtils.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ textMarkerUtils: function () { return textMarkerUtils; } }); var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); var toolManager; module.watch(require("./toolManager"), { toolManager: function (v) { toolManager = v; } }, 1); var viewportUtils; module.watch(require("./viewportUtils"), { viewportUtils: function (v) { viewportUtils = v; } }, 2); var changeTextCallback = function (data, eventData, doneChangingTextCallback) { // This handles the double-click/long-press event on Spine text marker labels var keyPressHandler = function (e) { // If Enter or Esc are pressed, close the dialog if (e.which === 13 || e.which === 27) { closeHandler(); } }; // Deactivate textMarker tool after editing a spine label & if spine is not active tool var deactivateAfterEdit = function () { if (toolManager.getActiveTool() !== 'spine') { var element = viewportUtils.getActiveViewportElement(); cornerstoneTools.textMarker.deactivate(element, 1); } }; var closeHandler = function () { dialog.get(0).close(); doneChangingTextCallback(data, select.val()); deactivateAfterEdit(); // Reset the focus to the active viewport element // This makes the mobile Safari keyboard close var element = viewportUtils.getActiveViewportElement(); $(element).focus(); }; var dialog = $('#textMarkerRelabelDialog'); // Is necessary to use Blaze object to not create // circular depencency with helper object (./helpers) if (Blaze._globalHelpers.isTouchDevice()) { // Center the dialog on screen on touch devices dialog.css({ top: 0, left: 0, right: 0, bottom: 0, margin: 'auto' }); dialog.find('.dialog.arrow').hide(); } else { // Place the dialog above the tool that is being relabelled // TODO = Switch this to the tool coordinates, but put back into // page coordinates. dialog.css({ top: eventData.currentPoints.page.y - dialog.outerHeight() - 20, left: eventData.currentPoints.page.x - dialog.outerWidth() / 2 }); dialog.find('.dialog.arrow').show(); } var select = dialog.find('.relabelSelect'); var confirm = dialog.find('.relabelConfirm'); var remove = dialog.find('.relabelRemove'); // If the remove button is clicked, delete this marker remove.off('click'); remove.on('click', function () { dialog.get(0).close(); doneChangingTextCallback(data, undefined, true); deactivateAfterEdit(); }); dialog.get(0).showModal(); $('.relabelSelect').val(data.text).trigger('change'); //Update selector to the current confirm.off('click'); confirm.on('click', function () { closeHandler(); }); // Use keydown since keypress doesn't handle ESC in Chrome dialog.off('keydown'); dialog.on('keydown', keyPressHandler); }; var textMarkerUtils = { changeTextCallback: changeTextCallback }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"thumbnailDragHandlers.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/thumbnailDragHandlers.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ thumbnailDragHandlers: function () { return thumbnailDragHandlers; } }); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 0); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 1); var cloneElement = function (element, targetId) { // Clone the DOM element var clone = element.cloneNode(true); // Find any canvas children to clone var clonedCanvases = $(clone).find('canvas'); clonedCanvases.each(function (canvasIndex, clonedCanvas) { // Draw from the original canvas to the cloned canvas var context = clonedCanvas.getContext('2d'); var thumbnailCanvas = $(element).find('canvas').get(canvasIndex); context.drawImage(thumbnailCanvas, 0, 0); }); // Update the clone with the targetId clone.id = targetId; clone.style.visibility = 'hidden'; return clone; }; var thumbnailDragStartHandler = function (event, data) { // Prevent any scrolling behaviour normally caused by the original event event.originalEvent.preventDefault(); // Identify the current study and series index from the thumbnail's DOM position var targetThumbnail = event.currentTarget; var $imageThumbnail = $(targetThumbnail); // Force to hardware acceleration to move element // if browser supports translate property var useTransform = OHIF.ui.styleProperty.check('transform', 'translate(1px, 1px)'); // Clone the image thumbnail var targetId = 'DragClone'; var clone = cloneElement(targetThumbnail, targetId); var $clone = $(clone); $clone.addClass('imageThumbnailClone'); // Set pointerEvents to pass through the clone DOM element // This is necessary in order to identify what is below it // when using document.elementFromPoint clone.style.pointerEvents = 'none'; // Append the clone to the body document.body.appendChild(clone); // Set the cursor x and y positions from the current touch/mouse coordinates var cursorX; var cursorY; // Handle touchStart cases if (event.type === 'touchstart') { cursorX = event.originalEvent.touches[0].pageX; cursorY = event.originalEvent.touches[0].pageY; } else { cursorX = event.pageX; cursorY = event.pageY; // Also hook up event handlers for mouse events var handlers = {}; handlers.mousemove = function (event) { return thumbnailDragHandler(event); }; handlers.mouseup = function (event) { return thumbnailDragEndHandler(event, data, handlers); }; $(document).on('mousemove', handlers.mousemove); $(document).on('mouseup', handlers.mouseup); } // This block gets the current offset of the touch/mouse // relative to the window // // i.e. Where did the user grab it from? var offset = $imageThumbnail.offset(); var left = offset.left, top = offset.top; // This difference is saved for later so the element movement looks normal var diff = { x: cursorX - left, y: cursorY - top }; $clone.data('diff', diff); $clone.css({ visibility: 'hidden', 'z-index': 100000 }); // This sets the default style properties of the cloned element so it is // ready to be dragged around the page if (useTransform) { var viewerHeight = $('#viewer').height(); var headerHeight = $('.header').outerHeight(); var heightDiff = viewerHeight + headerHeight; // Save height difference for later to set top position of the element during movement $clone.data('heightDiff', heightDiff); var positionX = cursorX - diff.x; var positionY = cursorY - diff.y - heightDiff; var translation = "translate(" + positionX + "px, " + positionY + "px)"; OHIF.ui.styleProperty.set($clone.get(0), 'transform', translation); } else { $clone.css({ left: cursorX - diff.x, position: 'fixed', top: cursorY - diff.y }); } }; var thumbnailDragHandler = function (event) { // Get the touch/mouse coordinates from the event var cursorX; var cursorY; if (event.type === 'touchmove') { cursorX = event.originalEvent.changedTouches[0].pageX; cursorY = event.originalEvent.changedTouches[0].pageY; } else { cursorX = event.pageX; cursorY = event.pageY; } // Find the clone element and update it's position on the page var $clone = $('#DragClone'); var diff = $clone.data('diff'); // Force to hardware acceleration to move element // if browser supports translate property var useTransform = OHIF.ui.styleProperty.check('transform', 'translate(1px, 1px)'); $clone.css({ visibility: 'visible', 'z-index': 100000 }); // This sets the default style properties of the cloned element so it is // ready to be dragged around the page if (useTransform) { var heightDiff = $clone.data('heightDiff'); var positionX = cursorX - diff.x; var positionY = cursorY - diff.y - heightDiff; var translation = "translate(" + positionX + "px, " + positionY + "px)"; OHIF.ui.styleProperty.set($clone.get(0), 'transform', translation); } else { $clone.css({ left: cursorX - diff.x, position: 'fixed', top: cursorY - diff.y }); } // Identify the element below the current cursor position var elemBelow = document.elementFromPoint(cursorX, cursorY); // If none exists, stop here if (!elemBelow) { return; } // Remove any current faded effects on viewports $('.viewportContainer canvas').removeClass('faded'); // Figure out what to do depending on what we're dragging over var $viewportsDraggedOver = $(elemBelow).parents('.viewportContainer'); if ($viewportsDraggedOver.length) { // If we're dragging over a non-empty viewport, fade it and change the cursor style $viewportsDraggedOver.find('canvas').not('.magnifyTool').addClass('faded'); document.body.style.cursor = 'copy'; } else if (elemBelow.classList.contains('viewportContainer') && elemBelow.classList.contains('empty')) { // If we're dragging over an empty viewport, just change the cursor style document.body.style.cursor = 'copy'; } else { // Otherwise, keep the cursor as no-drop style document.body.style.cursor = 'no-drop'; } }; var thumbnailDragEndHandler = function (event, data, handlers) { // Remove the mouse event listeners if (handlers) { $(document).off('mousemove', handlers.mousemove); $(document).off('mouseup', handlers.mouseup); } // Reset the cursor style to the default document.body.style.cursor = 'auto'; // Get the cloned element var $clone = $('#DragClone'); // If it doesn't exist, stop here if (!$clone.length) { return; } var offset = $clone.offset(); var top = offset.top, left = offset.left; var diff = $clone.data('diff'); // Identify the element below the cloned element position var elemBelow = document.elementFromPoint(left + diff.x, top + diff.y); // Remove all cloned elements from the page $('.imageThumbnailClone').remove(); // Remove any current faded effects on viewports $('.viewportContainer canvas').removeClass('faded'); // If none exists, stop here if (!elemBelow) { return; } // Remove any fade effects on the element below elemBelow.classList.remove('faded'); var element; var $viewportsDraggedOver = $(elemBelow).closest('.viewportContainer'); if ($viewportsDraggedOver.length) { // If we're dragging over a non-empty viewport, retrieve it element = $viewportsDraggedOver.get(0); } else if (elemBelow.classList.contains('viewportContainer') && elemBelow.classList.contains('empty')) { // If we're dragging over an empty viewport, retrieve that instead element = elemBelow; } else { // Otherwise, stop here return false; } // If there is no stored drag and drop data, stop here if (!data) { return false; } // Get the dropped viewport index var viewportIndex = $('.viewportContainer').index(element); // Rerender the viewport using the dragged thumbnail data OHIF.viewerbase.layoutManager.rerenderViewportWithNewDisplaySet(viewportIndex, data); return false; }; var thumbnailDragHandlers = { thumbnailDragEndHandler: thumbnailDragEndHandler, thumbnailDragStartHandler: thumbnailDragStartHandler, thumbnailDragHandler: thumbnailDragHandler }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"toolManager.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/toolManager.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ toolManager: function () { return toolManager; } }); var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 1); var Random; module.watch(require("meteor/random"), { Random: function (v) { Random = v; } }, 2); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 3); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 4); var cornerstone, cornerstoneTools; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; }, cornerstoneTools: function (v) { cornerstoneTools = v; } }, 5); var getFrameOfReferenceUID; module.watch(require("./getFrameOfReferenceUID"), { getFrameOfReferenceUID: function (v) { getFrameOfReferenceUID = v; } }, 6); var updateCrosshairsSynchronizer; module.watch(require("./updateCrosshairsSynchronizer"), { updateCrosshairsSynchronizer: function (v) { updateCrosshairsSynchronizer = v; } }, 7); var crosshairsSynchronizers; module.watch(require("./crosshairsSynchronizers"), { crosshairsSynchronizers: function (v) { crosshairsSynchronizers = v; } }, 8); var annotateTextUtils; module.watch(require("./annotateTextUtils"), { annotateTextUtils: function (v) { annotateTextUtils = v; } }, 9); var textMarkerUtils; module.watch(require("./textMarkerUtils"), { textMarkerUtils: function (v) { textMarkerUtils = v; } }, 10); var isTouchDevice; module.watch(require("./helpers/isTouchDevice"), { isTouchDevice: function (v) { isTouchDevice = v; } }, 11); var defaultTool = { left: 'wwwc', right: 'zoom', middle: 'pan' }; var activeTool; var defaultMouseButtonTools; var tools = {}; var gestures = { zoomTouchPinch: { enabled: true }, panMultiTouch: { enabled: true, numPointers: 2 }, stackScrollMultiTouch: { enabled: true, numPointers: 3 }, doubleTapZoom: { enabled: true } }; var toolDefaultStates = { activate: [], deactivate: ['length', 'angle', 'annotate', 'ellipticalRoi', 'rectangleRoi', 'spine'], enable: [], disable: [], disabledToolButtons: [], shadowConfig: { shadow: false, shadowColor: '#000000', shadowOffsetX: 0, shadowOffsetY: 0 }, textBoxConfig: { centering: { x: true, y: true } } }; var initialized = false; /** * Exported "toolManager" Singleton */ var toolManager = { init: function () { toolManager.addTool('wwwc', { mouse: cornerstoneTools.wwwc, touch: cornerstoneTools.wwwcTouchDrag }); toolManager.addTool('zoom', { mouse: cornerstoneTools.zoom, touch: cornerstoneTools.zoomTouchDrag }); toolManager.addTool('wwwcRegion', { mouse: cornerstoneTools.wwwcRegion, touch: cornerstoneTools.wwwcRegionTouch }); toolManager.addTool('dragProbe', { mouse: cornerstoneTools.dragProbe, touch: cornerstoneTools.dragProbeTouch }); toolManager.addTool('pan', { mouse: cornerstoneTools.pan, touch: cornerstoneTools.panTouchDrag, multiTouch: cornerstoneTools.panMultiTouch }); toolManager.addTool('stackScroll', { mouse: cornerstoneTools.stackScroll, touch: cornerstoneTools.stackScrollTouchDrag, multiTouch: cornerstoneTools.stackScrollMultiTouch }); toolManager.addTool('length', { mouse: cornerstoneTools.length, touch: cornerstoneTools.lengthTouch }); toolManager.addTool('angle', { mouse: cornerstoneTools.simpleAngle, touch: cornerstoneTools.simpleAngleTouch }); toolManager.addTool('magnify', { mouse: cornerstoneTools.magnify, touch: cornerstoneTools.magnifyTouchDrag }); toolManager.addTool('ellipticalRoi', { mouse: cornerstoneTools.ellipticalRoi, touch: cornerstoneTools.ellipticalRoiTouch }); toolManager.addTool('rectangleRoi', { mouse: cornerstoneTools.rectangleRoi, touch: cornerstoneTools.rectangleRoiTouch }); toolManager.addTool('annotate', { mouse: cornerstoneTools.arrowAnnotate, touch: cornerstoneTools.arrowAnnotateTouch }); toolManager.addTool('rotate', { mouse: cornerstoneTools.rotate, touch: cornerstoneTools.rotateTouchDrag }); toolManager.addTool('spine', { mouse: cornerstoneTools.textMarker, touch: cornerstoneTools.textMarkerTouch }); toolManager.addTool('crosshairs', { mouse: cornerstoneTools.crosshairs, touch: cornerstoneTools.crosshairsTouch }); toolManager.addTool('scaleOverlayTool', { mouse: cornerstoneTools.scaleOverlayTool }); // if a default tool is globally defined, make it the default tool... if (OHIF.viewer.defaultTool) { this.setDefaultTool(OHIF.viewer.defaultTool); } defaultMouseButtonTools = Meteor.settings && Meteor.settings.public && Meteor.settings.public.defaultMouseButtonTools; // Override default tool if defined in settings if (defaultMouseButtonTools) { if (defaultMouseButtonTools.left) { this.setDefaultTool(defaultMouseButtonTools.left); } if (defaultMouseButtonTools.right) { this.setDefaultTool(defaultMouseButtonTools.right, 'right'); } if (defaultMouseButtonTools.middle) { this.setDefaultTool(defaultMouseButtonTools.middle, 'middle'); } } this.configureTools(); initialized = true; }, configureTools: function () { // Get Cornerstone Tools var _cornerstoneTools = cornerstoneTools, textStyle = _cornerstoneTools.textStyle, toolStyle = _cornerstoneTools.toolStyle, toolColors = _cornerstoneTools.toolColors, length = _cornerstoneTools.length, arrowAnnotate = _cornerstoneTools.arrowAnnotate, zoom = _cornerstoneTools.zoom, ellipticalRoi = _cornerstoneTools.ellipticalRoi, textMarker = _cornerstoneTools.textMarker, magnify = _cornerstoneTools.magnify; // Set text box background color textStyle.setBackgroundColor('transparent'); // Set the tool font and font size // context.font = "[style] [variant] [weight] [size]/[line height] [font family]"; var fontFamily = 'Roboto, OpenSans, HelveticaNeue-Light, Helvetica Neue Light, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif'; textStyle.setFont('15px ' + fontFamily); // Set the tool width toolStyle.setToolWidth(2); // Set color for inactive tools toolColors.setToolColor('rgb(255, 255, 0)'); // yellow // Set color for active tools toolColors.setActiveColor('rgb(50, 205, 50)'); // limegreen // Set shadow configuration var shadowConfig = toolManager.getToolDefaultStates().shadowConfig; // Get some tools config to not override them var lengthConfig = length.getConfiguration(); var ellipticalRoiConfig = ellipticalRoi.getConfiguration(); // Add shadow to length tool length.setConfiguration(Object.assign({}, lengthConfig, shadowConfig, { drawHandlesOnHover: true })); // Add shadow to length tool ellipticalRoi.setConfiguration(Object.assign({}, ellipticalRoiConfig, shadowConfig)); // Set the configuration values for the Text Marker (Spine Labelling) tool var $startFrom = $('#startFrom'); var $ascending = $('#ascending'); var textMarkerConfig = { markers: ['L5', 'L4', 'L3', 'L2', 'L1', // Lumbar spine 'T12', 'T11', 'T10', 'T9', 'T8', 'T7', // Thoracic spine 'T6', 'T5', 'T4', 'T3', 'T2', 'T1', 'C7', 'C6', 'C5', 'C4', 'C3', 'C2', 'C1'], current: $startFrom.val(), ascending: $ascending.is(':checked'), loop: true, changeTextCallback: textMarkerUtils.changeTextCallback, shadow: shadowConfig.shadow, shadowColor: shadowConfig.shadowColor, shadowOffsetX: shadowConfig.shadowOffsetX, shadowOffsetY: shadowConfig.shadowOffsetY }; textMarker.setConfiguration(textMarkerConfig); // Set the configuration values for the text annotation (Arrow) tool var annotateConfig = { getTextCallback: annotateTextUtils.getTextCallback, changeTextCallback: annotateTextUtils.changeTextCallback, drawHandles: false, arrowFirst: true }; arrowAnnotate.setConfiguration(annotateConfig); var zoomConfig = { minScale: 0.05, maxScale: 10 }; zoom.setConfiguration(zoomConfig); var magnifyConfig = { magnifySize: 300, magnificationLevel: 3 }; magnify.setConfiguration(magnifyConfig); if (Meteor.settings && Meteor.settings.public && Meteor.settings.public.defaultGestures) { gestures.zoomTouchPinch = Meteor.settings.public.defaultGestures.zoomTouchPinch || gestures.zoomTouchPinch; gestures.stackScrollMultiTouch = Meteor.settings.public.defaultGestures.stackScrollMultiTouch || gestures.stackScrollMultiTouch; gestures.panMultiTouch = Meteor.settings.public.defaultGestures.panMultiTouch || gestures.panMultiTouch; gestures.doubleTapZoom = Meteor.settings.public.defaultGestures.doubleTapZoom || gestures.doubleTapZoom; } // Set number of fingers to stack scroll if (gestures.stackScrollMultiTouch.enabled === true && gestures.stackScrollMultiTouch.numPointers) { var stackScrollMultiTouchConfig = { testPointers: function (eventData) { return eventData.numPointers === gestures.stackScrollMultiTouch.numPointers; } }; cornerstoneTools.stackScrollMultiTouch.setConfiguration(stackScrollMultiTouchConfig); } // Set number of fingers to pan if (gestures.panMultiTouch.enabled === true && gestures.panMultiTouch.numPointers) { var panMultiTouchConfig = { testPointers: function (eventData) { return eventData.numPointers === gestures.panMultiTouch.numPointers; } }; cornerstoneTools.panMultiTouch.setConfiguration(panMultiTouchConfig); } }, /** * This function searches an object to return the keys that contain a specific value * * @param object {object} The object to be searched * @param value The value to be found * * @returns {array} The keys for which the object has the specified value */ getKeysByValue: function (object, value) { // http://stackoverflow.com/questions/9907419/javascript-object-get-key-by-value return Object.keys(object).filter(function (key) { return object[key] === value; }); }, configureLoadProcess: function () { // Whenever CornerstoneImageLoadProgress is fired, identify which viewports // the "in-progress" image is to be displayed in. Then pass the percent complete // via the Meteor Session to the other templates to be displayed in the relevant viewports. function handleLoadProgress(e) { var eventData = e.detail; var viewportIndices = toolManager.getKeysByValue(window.ViewportLoading, eventData.imageId); viewportIndices.forEach(function (viewportIndex) { Session.set('CornerstoneLoadProgress' + viewportIndex, eventData.percentComplete); }); var encodedId = OHIF.string.encodeId(eventData.imageId); Session.set('CornerstoneThumbnailLoadProgress' + encodedId, eventData.percentComplete); } cornerstone.events.removeEventListener('cornerstoneimageloadprogress', handleLoadProgress); cornerstone.events.addEventListener('cornerstoneimageloadprogress', handleLoadProgress); }, setGestures: function (newGestures) { gestures = newGestures; }, getGestures: function () { return gestures; }, addTool: function (name, base) { tools[name] = base; }, getTools: function () { return tools; }, setToolDefaultStates: function (states) { toolDefaultStates = states; }, getToolDefaultStates: function () { return toolDefaultStates; }, setActiveToolForElement: function (toolId, element, button) { var canvases = $(element).find('canvas'); if (element.classList.contains('empty') || !canvases.length) { return; } // If button is not defined, we should consider it left if (!button) { button = 'left'; } // First, deactivate the current active tool tools[activeTool.left].mouse.deactivate(element, 1); // 1 means left mouse button tools[activeTool.middle].mouse.deactivate(element, 2); // 2 means middle mouse button tools[activeTool.right].mouse.deactivate(element, 4); // 3 means right mouse button if (tools[activeTool.left].touch) { tools[activeTool.left].touch.deactivate(element); } if (tools[activeTool.right].multiTouch) { tools[activeTool.right].multiTouch.disable(element); } // Enable tools based on their default states Object.keys(toolDefaultStates).forEach(function (action) { var relevantTools = toolDefaultStates[action]; if (!relevantTools || !relevantTools.length || action === 'disabledToolButtons') return; relevantTools.forEach(function (toolType) { // the currently active tool has already been deactivated and can be skipped if (action === 'deactivate' && (toolType === activeTool.left || toolType === activeTool.middle || toolType === activeTool.right)) { return; } tools[toolType].mouse[action](element, action === 'activate' || action === 'deactivate' ? 1 : void 0); if (tools[toolType].touch) { tools[toolType].touch[action](element); } if (tools[toolType].multiTouch) { tools[toolType].multiTouch[action](element); } }); }); // Get the stack toolData var toolData = cornerstoneTools.getToolState(element, 'stack'); if (!toolData || !toolData.data || !toolData.data.length) { return; } // Get the imageIds for this element var imageIds = toolData.data[0].imageIds; // Get the mouse button tools var newToolIdLeft = activeTool.left; if (button === 'left') { newToolIdLeft = toolId; } var newCornerstoneToolLeft = tools[newToolIdLeft]; // left mouse tool is used for touch as well var newToolIdMiddle = activeTool.middle; if (button === 'middle') { newToolIdMiddle = toolId; } var newCornerstoneToolMiddle = cornerstoneTools[newToolIdMiddle]; var newToolIdRight = activeTool.right; if (button === 'right') { newToolIdRight = toolId; } var newCornerstoneToolRight = tools[newToolIdRight]; // right mouse tool is used for multi-touch as well // Deactivate scroll wheel tools cornerstoneTools.zoomWheel.deactivate(element); cornerstoneTools.stackScrollWheel.deactivate(element); cornerstoneTools.panMultiTouch.disable(element); cornerstoneTools.zoomTouchPinch.disable(element); cornerstoneTools.stackScrollMultiTouch.disable(element); cornerstoneTools.doubleTapZoom.disable(element); // Reactivate the relevant scrollwheel tool for this element if (imageIds.length > 1) { // scroll is the default tool for middle mouse wheel for stacks cornerstoneTools.stackScrollWheel.activate(element); // 3 or more finger stack scroll if (gestures.stackScrollMultiTouch.enabled === true && gestures.stackScrollMultiTouch.numPointers >= 3) { var stackScrollMultiTouchConfig = { testPointers: function (eventData) { return eventData.numPointers === gestures.stackScrollMultiTouch.numPointers; } }; cornerstoneTools.stackScrollMultiTouch.setConfiguration(stackScrollMultiTouchConfig); cornerstoneTools.stackScrollMultiTouch.activate(element); } } else { // zoom is the default tool for middle mouse wheel for single images (non stacks) cornerstoneTools.zoomWheel.activate(element); } // 3 or more finger pan if (gestures.panMultiTouch.enabled === true && gestures.panMultiTouch.numPointers >= 3) { var panMultiTouchConfig = { testPointers: function (eventData) { return eventData.numPointers === gestures.panMultiTouch.numPointers; } }; cornerstoneTools.panMultiTouch.setConfiguration(panMultiTouchConfig); cornerstoneTools.panMultiTouch.activate(element); } // TODO: Remove this messy approach for adding synchronizer when necessary. var leftToolSynchronizer; if (newToolIdLeft === 'crosshairs') { var currentFrameOfReferenceUID = getFrameOfReferenceUID(element); if (currentFrameOfReferenceUID) { updateCrosshairsSynchronizer(currentFrameOfReferenceUID); leftToolSynchronizer = crosshairsSynchronizers.synchronizers[currentFrameOfReferenceUID]; } if (newToolIdLeft === newToolIdMiddle && newToolIdMiddle === newToolIdRight) { newCornerstoneToolRight.mouse.activate(element, 7); // 7 means left mouse button, right mouse button and middle mouse button } else if (newToolIdLeft === newToolIdMiddle) { newCornerstoneToolMiddle.activate(element, 3); // 3 means left mouse button and middle mouse button newCornerstoneToolRight.mouse.activate(element, 4); // 4 means right mouse button } else if (newToolIdMiddle === newToolIdRight) { newCornerstoneToolRight.mouse.activate(element, 6); // 6 means right mouse button and middle mouse button newCornerstoneToolLeft.mouse.activate(element, 1, leftToolSynchronizer); // 1 means left mouse button } else if (newToolIdLeft === newToolIdRight) { newCornerstoneToolMiddle.activate(element, 2); // 2 means middle mouse button newCornerstoneToolRight.mouse.activate(element, 5); // 5 means left mouse button and right mouse button } else { newCornerstoneToolLeft.mouse.activate(element, 1, leftToolSynchronizer); // 1 means left mouse button newCornerstoneToolMiddle.activate(element, 2); // 2 means middle mouse button newCornerstoneToolRight.mouse.activate(element, 4); // 4 means right mouse button } } else { // This block ensures that all mouse button tools keep working if (newToolIdLeft === newToolIdMiddle && newToolIdMiddle === newToolIdRight) { newCornerstoneToolRight.mouse.activate(element, 7); // 7 means left mouse button, right mouse button and middle mouse button } else if (newToolIdLeft === newToolIdMiddle) { newCornerstoneToolMiddle.activate(element, 3); // 3 means left mouse button and middle mouse button newCornerstoneToolRight.mouse.activate(element, 4); // 4 means right mouse button } else if (newToolIdMiddle === newToolIdRight) { newCornerstoneToolRight.mouse.activate(element, 6); // 6 means right mouse button and middle mouse button newCornerstoneToolLeft.mouse.activate(element, 1); // 1 means left mouse button } else if (newToolIdLeft === newToolIdRight) { newCornerstoneToolMiddle.activate(element, 2); // 2 means middle mouse button newCornerstoneToolRight.mouse.activate(element, 5); // 5 means left mouse button and right mouse button } else { setTimeout(function () { return newCornerstoneToolLeft.mouse.activate(element, 1); }); // >>>> TODO Find out why it's working only with a timeout // newCornerstoneToolLeft.mouse.activate(element, 1); // 1 means left mouse button newCornerstoneToolMiddle.activate(element, 2); // 2 means middle mouse button newCornerstoneToolRight.mouse.activate(element, 4); // 4 means right mouse button } } // One finger touch if (newCornerstoneToolLeft.touch) { if (leftToolSynchronizer) { newCornerstoneToolLeft.touch.activate(element, leftToolSynchronizer); } else { newCornerstoneToolLeft.touch.activate(element); } } // Two finger swipe var twoFingerMultiTouchConfig = { testPointers: function (eventData) { return eventData.numPointers === 2; } }; if (newCornerstoneToolRight.multiTouch) { newCornerstoneToolRight.multiTouch.setConfiguration(twoFingerMultiTouchConfig); newCornerstoneToolRight.multiTouch.activate(element); } else if (gestures.panMultiTouch.enabled === true && gestures.panMultiTouch.numPointers === 2) { cornerstoneTools.panMultiTouch.setConfiguration(twoFingerMultiTouchConfig); cornerstoneTools.panMultiTouch.activate(element); } else if (gestures.stackScrollMultiTouch.enabled === true && gestures.stackScrollMultiTouch.numPointers === 2) { cornerstoneTools.stackScrollMultiTouch.setConfiguration(twoFingerMultiTouchConfig); cornerstoneTools.stackScrollMultiTouch.activate(element); } // Two finger pinch if (gestures.zoomTouchPinch.enabled === true) { cornerstoneTools.zoomTouchPinch.activate(element); } // Double Tap if (gestures.doubleTapZoom.enabled === true) { cornerstoneTools.doubleTapZoom.activate(element); } }, setActiveTool: function (toolId, elements, button) { if (!initialized) { toolManager.init(); } var $elements; if (!elements || !elements.length) { $elements = $('.imageViewerViewport'); } else { $elements = $(elements); } var checkElementEnabled = function (allElementsEnabled, element) { try { cornerstone.getEnabledElement(element); return allElementsEnabled; } catch (error) { return true; } }; if (!activeTool) { activeTool = defaultTool; } // If button is not defined, we should consider it left if (!button) { button = 'left'; } var activeToolId = activeTool[button]; /** * TODO: Add textMarkerDialogs template to OHIF's */ var dialog = document.getElementById('textMarkerOptionsDialog'); if (dialog) { if (toolId === 'spine' && activeToolId !== 'spine' && dialog.getAttribute('open') !== 'open') { dialog.show(); } else if (activeToolId !== 'spine' && dialog.getAttribute('open') === 'open') { dialog.close(); } } if (!toolId) { toolId = this.getDefaultTool(button); } // Otherwise, set the active tool for all viewport elements $elements.each(function (index, element) { if (checkElementEnabled(element) === false) { return; } toolManager.setActiveToolForElement(toolId, element, button); }); activeTool[button] = toolId; // Enable reactivity Session.set('ToolManagerActiveToolUpdated', Random.id()); }, getNearbyToolData: function (element, coords, toolTypes) { var allTools = this.getTools(); var touchDevice = isTouchDevice(); var nearbyTool = {}; var pointNearTool = false; toolTypes.forEach(function (toolType) { var toolData = cornerstoneTools.getToolState(element, toolType); if (!toolData) { return; } toolData.data.forEach(function (data, index) { var toolInterfaceName = toolType; var toolInterface; // Edge cases where the tool is not the same as the typeName if (toolType === 'simpleAngle') { toolInterfaceName = 'angle'; } else if (toolType === 'arrowAnnotate') { toolInterfaceName = 'annotate'; } if (touchDevice) { toolInterface = allTools[toolInterfaceName].touch; } else { toolInterface = allTools[toolInterfaceName].mouse; } if (toolInterface.pointNearTool(element, data, coords)) { pointNearTool = true; nearbyTool.tool = data; nearbyTool.index = index; nearbyTool.toolType = toolType; } }); if (pointNearTool) { return false; } }); return pointNearTool ? nearbyTool : undefined; }, getActiveTool: function (button) { if (!initialized) { toolManager.init(); } // If activeTool is not defined, we should set as defaultTool if (!activeTool) { activeTool = defaultTool; } // If button is not defined, we should consider it left if (!button) { button = 'left'; } return activeTool[button]; }, setDefaultTool: function (tool, button) { // If button is not defined, we should consider it left if (!button) { button = 'left'; } defaultTool[button] = tool; }, getDefaultTool: function (button) { // If button is not defined, we should consider it left if (!button) { button = 'left'; } return defaultTool[button]; }, setConfigureTools: function (configureTools) { if (typeof configureTools === 'function') { this.configureTools = configureTools; } }, activateCommandButton: function (button) { var activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || []; if (activeCommandButtons.indexOf(button) === -1) { activeCommandButtons.push(button); Session.set('ToolManagerActiveCommandButtons', activeCommandButtons); } }, deactivateCommandButton: function (button) { var activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || []; var index = activeCommandButtons.indexOf(button); if (index !== -1) { activeCommandButtons.splice(index, 1); Session.set('ToolManagerActiveCommandButtons', activeCommandButtons); } } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"unloadHandlers.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/unloadHandlers.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ unloadHandlers: function () { return unloadHandlers; } }); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); var unloadHandlers = { beforeUnload: function (event) { // Check for any unsaved changes on viewer namespace... if (OHIF.ui.unsavedChanges.probe('viewer.*') > 0) { var confirmationMessage = 'You have unsaved changes!'; event.returnValue = confirmationMessage; return confirmationMessage; } } }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"updateAllViewports.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/updateAllViewports.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ updateAllViewports: function () { return updateAllViewports; } }); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 0); function updateAllViewports() { var viewports = $('.imageViewerViewport').not('.empty'); viewports.each(function (index, element) { cornerstone.updateImage(element); }); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"updateCrosshairsSynchronizer.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/updateCrosshairsSynchronizer.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ updateCrosshairsSynchronizer: function () { return updateCrosshairsSynchronizer; } }); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 0); var getFrameOfReferenceUID; module.watch(require("./getFrameOfReferenceUID"), { getFrameOfReferenceUID: function (v) { getFrameOfReferenceUID = v; } }, 1); var crosshairsSynchronizers; module.watch(require("./crosshairsSynchronizers"), { crosshairsSynchronizers: function (v) { crosshairsSynchronizers = v; } }, 2); function updateCrosshairsSynchronizer(currentFrameOfReferenceUID) { // Check if an old synchronizer exists, and if it does, destroy it // If not, create a new one var synchronizer = crosshairsSynchronizers.synchronizers[currentFrameOfReferenceUID]; if (synchronizer) { // If it already exists, remove all source & target elements synchronizer.destroy(); } else { // Create a new synchronizer crosshairsSynchronizers.synchronizers[currentFrameOfReferenceUID] = new cornerstoneTools.Synchronizer('cornerstonenewimage', cornerstoneTools.updateImageSynchronizer); synchronizer = crosshairsSynchronizers.synchronizers[currentFrameOfReferenceUID]; } // Add all elements that stem from the same frame of reference $('.imageViewerViewport').each(function (index, element) { var frameOfReferenceUID = getFrameOfReferenceUID(element); if (currentFrameOfReferenceUID !== frameOfReferenceUID) { return; } synchronizer.add(element); }); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"updateMetaDataManager.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/updateMetaDataManager.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ updateMetaDataManager: function () { return updateMetaDataManager; } }); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 0); var getWADORSImageId; module.watch(require("./getWADORSImageId"), { getWADORSImageId: function (v) { getWADORSImageId = v; } }, 1); var WadoRsMetaDataBuilder; module.watch(require("./classes/metadata/WadoRsMetaDataBuilder"), { WadoRsMetaDataBuilder: function (v) { WadoRsMetaDataBuilder = v; } }, 2); function getRadiopharmaceuticalInfoMetaData(instance) { var radiopharmaceuticalInfo = instance.radiopharmaceuticalInfo; if (instance.modality !== 'PT' || !radiopharmaceuticalInfo) { return; } return new WadoRsMetaDataBuilder().addTag('00181072', radiopharmaceuticalInfo.radiopharmaceuticalStartTime).addTag('00181074', radiopharmaceuticalInfo.radionuclideTotalDose).addTag('00181075', radiopharmaceuticalInfo.radionuclideHalfLife).toJSON(); } var getWadoRsInstanceMetaData = function (study, series, instance) { return new WadoRsMetaDataBuilder().addTag('00080016', instance.sopClassUid).addTag('00080018', instance.sopInstanceUid).addTag('00080021', series.seriesDate).addTag('00080031', series.seriesTime).addTag('00080060', instance.modality).addTag('00101010', study.patientAge).addTag('00101020', study.patientSize).addTag('00101030', study.patientWeight).addTag('00180050', instance.sliceThickness).addTag('0020000e', series.seriesInstanceUid).addTag('00200011', series.seriesNumber).addTag('0020000d', study.studyInstanceUid).addTag('00200013', instance.instanceNumber).addTag('00200032', instance.imagePositionPatient, true).addTag('00200037', instance.imageOrientationPatient, true).addTag('00200052', instance.frameOfReferenceUID).addTag('00201041', instance.sliceLocation).addTag('00280002', instance.samplesPerPixel).addTag('00280004', instance.photometricInterpretation).addTag('00280006', instance.planarConfiguration).addTag('00280010', instance.rows).addTag('00280011', instance.columns).addTag('00280030', instance.pixelSpacing, true).addTag('00280034', instance.pixelAspectRatio, true).addTag('00280100', instance.bitsAllocated).addTag('00280101', instance.bitsStored).addTag('00280102', instance.highBit).addTag('00280103', instance.pixelRepresentation).addTag('00280106', instance.smallestPixelValue).addTag('00280107', instance.largestPixelValue).addTag('00281050', instance.windowCenter, true).addTag('00281051', instance.windowWidth, true).addTag('00281052', instance.rescaleIntercept).addTag('00281053', instance.rescaleSlope).addTag('00281054', instance.rescaleType).addTag('00281101', instance.redPaletteColorLookupTableDescriptor).addTag('00281102', instance.greenPaletteColorLookupTableDescriptor).addTag('00281103', instance.bluePaletteColorLookupTableDescriptor).addTag('00281201', instance.redPaletteColorLookupTableData).addTag('00281202', instance.greenPaletteColorLookupTableData).addTag('00281203', instance.bluePaletteColorLookupTableData).addTag('00540016', getRadiopharmaceuticalInfoMetaData(instance)).toJSON(); }; function updateMetaDataManager(study) { study.seriesList.forEach(function (series) { series.instances.forEach(function (instance) { // Cache just images that are going to be loaded via WADO-RS if (instance.imageRendering !== 'wadors' && instance.thumbnailRendering !== 'wadors') { return; } var metaData = getWadoRsInstanceMetaData(study, series, instance); var numberOfFrames = instance.numberOfFrames || 1; // We can share the same metaData with all frames because it doesn't have // any frame specific data, such as frameNumber, pixelData, offset, etc. // WADO-RS frame number is 1-based for (var frameNumber = 0; frameNumber < numberOfFrames; frameNumber++) { var imageId = getWADORSImageId(instance, frameNumber); cornerstoneWADOImageLoader.wadors.metaDataManager.add(imageId, metaData); } }); }); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"updateOrientationMarkers.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/updateOrientationMarkers.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ updateOrientationMarkers: function () { return updateOrientationMarkers; } }); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 0); function updateOrientationMarkers(element, viewport) { // Get the current viewport settings if (!viewport) { viewport = cornerstone.getViewport(element); } // Updates the orientation labels on the viewport var enabledElement = cornerstone.getEnabledElement(element); var imagePlane = cornerstone.metaData.get('imagePlane', enabledElement.image.imageId); if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) { return; } var rowString = cornerstoneTools.orientation.getOrientationString(imagePlane.rowCosines); var columnString = cornerstoneTools.orientation.getOrientationString(imagePlane.columnCosines); var oppositeRowString = cornerstoneTools.orientation.invertOrientationString(rowString); var oppositeColumnString = cornerstoneTools.orientation.invertOrientationString(columnString); var markers = { top: oppositeColumnString, left: oppositeRowString }; // If any vertical or horizontal flips are applied, change the orientation strings ahead of // the rotation applications if (viewport.vflip) { markers.top = cornerstoneTools.orientation.invertOrientationString(markers.top); } if (viewport.hflip) { markers.left = cornerstoneTools.orientation.invertOrientationString(markers.left); } // Get the viewport orientation marker DOM elements var viewportOrientationMarkers = $(element).siblings('.viewportOrientationMarkers'); var topMarker = viewportOrientationMarkers.find('.topMid'); var leftMarker = viewportOrientationMarkers.find('.leftMid'); // Swap the labels accordingly if the viewport has been rotated // This could be done in a more complex way for intermediate rotation values (e.g. 45 degrees) if (viewport.rotation === 90 || viewport.rotation === -270) { topMarker.text(markers.left); leftMarker.text(cornerstoneTools.orientation.invertOrientationString(markers.top)); } else if (viewport.rotation === -90 || viewport.rotation === 270) { topMarker.text(cornerstoneTools.orientation.invertOrientationString(markers.left)); leftMarker.text(markers.top); } else if (viewport.rotation === 180 || viewport.rotation === -180) { topMarker.text(cornerstoneTools.orientation.invertOrientationString(markers.top)); leftMarker.text(cornerstoneTools.orientation.invertOrientationString(markers.left)); } else { topMarker.text(markers.top); leftMarker.text(markers.left); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"viewportOverlayUtils.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/viewportOverlayUtils.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ viewportOverlayUtils: function () { return viewportOverlayUtils; } }); var cornerstone; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; } }, 0); var getElementIfNotEmpty; module.watch(require("./getElementIfNotEmpty"), { getElementIfNotEmpty: function (v) { getElementIfNotEmpty = v; } }, 1); var getPatient = function (property) { if (!this.imageId) { return false; } var patient = cornerstone.metaData.get('patient', this.imageId); if (!patient) { return ''; } return patient[property]; }; var getStudy = function (property) { if (!this.imageId) { return false; } var study = cornerstone.metaData.get('study', this.imageId); if (!study) { return ''; } return study[property]; }; var getSeries = function (property) { if (!this.imageId) { return false; } var series = cornerstone.metaData.get('series', this.imageId); if (!series) { return ''; } return series[property]; }; var getInstance = function (property) { if (!this.imageId) { return false; } var instance = cornerstone.metaData.get('instance', this.imageId); if (!instance) { return ''; } return instance[property]; }; var getTagDisplay = function (property) { if (!this.imageId) { return false; } var instance = cornerstone.metaData.get('tagDisplay', this.imageId); if (!instance) { return ''; } return instance[property]; }; var getImage = function (viewportIndex) { var element = getElementIfNotEmpty(viewportIndex); if (!element) { return false; } var enabledElement; try { enabledElement = cornerstone.getEnabledElement(element); } catch (error) { return false; } if (!enabledElement || !enabledElement.image) { return false; } return enabledElement.image; }; var formatDateTime = function (date, time) { return date + " " + time; }; var viewportOverlayUtils = { getPatient: getPatient, getStudy: getStudy, getSeries: getSeries, getInstance: getInstance, getTagDisplay: getTagDisplay, getImage: getImage, formatDateTime: formatDateTime }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"viewportUtils.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/viewportUtils.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ viewportUtils: function () { return viewportUtils; } }); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 0); var Random; module.watch(require("meteor/random"), { Random: function (v) { Random = v; } }, 1); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 2); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 3); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 4); var cornerstone, cornerstoneTools; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; }, cornerstoneTools: function (v) { cornerstoneTools = v; } }, 5); var updateOrientationMarkers; module.watch(require("./updateOrientationMarkers"), { updateOrientationMarkers: function (v) { updateOrientationMarkers = v; } }, 6); var getInstanceClassDefaultViewport; module.watch(require("./instanceClassSpecificViewport"), { getInstanceClassDefaultViewport: function (v) { getInstanceClassDefaultViewport = v; } }, 7); /** * Get a cornerstone enabledElement for a DOM Element * @param {DOMElement} element Element to get the enabledElement from Cornerstone * @return {Object} Cornerstone's enabledElement object for the given * element or undefined if the element is not enabled */ var getEnabledElement = function (element) { var enabledElement; try { enabledElement = cornerstone.getEnabledElement(element); } catch (error) { OHIF.log.warn(error); } return enabledElement; }; /** * Get the active viewport element. It uses activeViewport Session Variable * @return {DOMElement} DOMElement of the current active viewport */ var getActiveViewportElement = function () { var viewportIndex = Session.get('activeViewport') || 0; return $('.imageViewerViewport').get(viewportIndex); }; /** * Get a cornerstone enabledElement for the Active Viewport Element * @return {Object} Cornerstone's enabledElement object for the active * viewport element or undefined if the element * is not enabled */ var getEnabledElementForActiveElement = function () { var activeViewportElement = getActiveViewportElement(); var enabledElement = getEnabledElement(activeViewportElement); return enabledElement; }; var zoomIn = function () { var element = getActiveViewportElement(); if (!element) { return; } var viewport = cornerstone.getViewport(element); var scaleIncrement = 0.15; var maximumScale = 10; viewport.scale = Math.min(viewport.scale + scaleIncrement, maximumScale); cornerstone.setViewport(element, viewport); }; var zoomOut = function () { var element = getActiveViewportElement(); if (!element) { return; } var viewport = cornerstone.getViewport(element); var scaleIncrement = 0.15; var minimumScale = 0.05; viewport.scale = Math.max(viewport.scale - scaleIncrement, minimumScale); cornerstone.setViewport(element, viewport); }; var zoomToFit = function () { var element = getActiveViewportElement(); if (!element) { return; } cornerstone.fitToWindow(element); }; var rotateL = function () { var element = getActiveViewportElement(); if (!element) { return; } var viewport = cornerstone.getViewport(element); viewport.rotation -= 90; cornerstone.setViewport(element, viewport); updateOrientationMarkers(element, viewport); }; var rotateR = function () { var element = getActiveViewportElement(); if (!element) { return; } var viewport = cornerstone.getViewport(element); viewport.rotation += 90; cornerstone.setViewport(element, viewport); updateOrientationMarkers(element, viewport); }; var invert = function () { var element = getActiveViewportElement(); if (!element) { return; } var viewport = cornerstone.getViewport(element); viewport.invert = viewport.invert === false; cornerstone.setViewport(element, viewport); }; var flipV = function () { var element = getActiveViewportElement(); var viewport = cornerstone.getViewport(element); viewport.vflip = viewport.vflip === false; cornerstone.setViewport(element, viewport); updateOrientationMarkers(element, viewport); }; var flipH = function () { var element = getActiveViewportElement(); var viewport = cornerstone.getViewport(element); viewport.hflip = viewport.hflip === false; cornerstone.setViewport(element, viewport); updateOrientationMarkers(element, viewport); }; var resetViewportWithElement = function (element) { var enabledElement = cornerstone.getEnabledElement(element); if (enabledElement.fitToWindow === false) { var imageId = enabledElement.image.imageId; var instance = cornerstone.metaData.get('instance', imageId); enabledElement.viewport = cornerstone.getDefaultViewport(enabledElement.canvas, enabledElement.image); var instanceClassDefaultViewport = getInstanceClassDefaultViewport(instance, enabledElement, imageId); cornerstone.setViewport(element, instanceClassDefaultViewport); } else { cornerstone.reset(element); } }; var resetViewport = function () { var viewportIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; if (viewportIndex === null) { resetViewportWithElement(getActiveViewportElement()); } else if (viewportIndex === 'all') { $('.imageViewerViewport').each(function (index, element) { resetViewportWithElement(element); }); } else { resetViewportWithElement($('.imageViewerViewport').get(viewportIndex)); } }; var clearTools = function () { var element = getActiveViewportElement(); var toolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager; toolStateManager.clear(element); cornerstone.updateImage(element); }; var linkStackScroll = function () { var synchronizer = OHIF.viewer.stackImagePositionOffsetSynchronizer; if (!synchronizer) { return; } if (synchronizer.isActive()) { synchronizer.deactivate(); } else { synchronizer.activate(); } }; // This function was originally defined alone inside client/lib/toggleDialog.js // and has been moved here to avoid circular dependency issues. var toggleDialog = function (element, closeAction) { var $element = $(element); if ($element.is('dialog')) { if (element.hasAttribute('open')) { if (closeAction) { closeAction(); } element.close(); } else { element.show(); } } else { var isClosed = $element.hasClass('dialog-open'); $element.toggleClass('dialog-closed', isClosed); $element.toggleClass('dialog-open', !isClosed); } }; // Toggle the play/stop state for the cornerstone clip tool var toggleCinePlay = function () { // Get the active viewport element var element = getActiveViewportElement(); // Check if it's playing the clip to toggle it if (isPlaying()) { cornerstoneTools.stopClip(element); } else { cornerstoneTools.playClip(element); } // Update the UpdateCINE session property Session.set('UpdateCINE', Math.random()); }; // Show/hide the CINE dialog var toggleCineDialog = function () { var dialog = document.getElementById('cineDialog'); toggleDialog(dialog, stopAllClips); Session.set('UpdateCINE', Random.id()); }; var toggleDownloadDialog = function () { stopActiveClip(); var $dialog = $('#imageDownloadDialog'); if ($dialog.length) { $dialog.find('.close:first').click(); } else { OHIF.ui.showDialog('imageDownloadDialog'); } }; var isDownloadEnabled = function () { var activeViewport = getActiveViewportElement(); return activeViewport ? true : false; }; // Check if the clip is playing on the active viewport var isPlaying = function () { // Create a dependency on LayoutManagerUpdated and UpdateCINE session Session.get('UpdateCINE'); Session.get('LayoutManagerUpdated'); // Get the viewport element and its current playClip tool state var element = getActiveViewportElement(); // Empty Elements throws cornerstore exception if (!element || !$(element).find('canvas').length) { return; } var toolState = cornerstoneTools.getToolState(element, 'playClip'); // Stop here if the tool state is not defined yet if (!toolState) { return false; } // Get the clip state var clipState = toolState.data[0]; if (clipState) { // Return true if the clip is playing return !_.isUndefined(clipState.intervalId); } return false; }; // Check if a study has multiple frames var hasMultipleFrames = function () { // Its called everytime active viewport and/or layout change Session.get('activeViewport'); Session.get('LayoutManagerUpdated'); var activeViewport = getActiveViewportElement(); // No active viewport yet: disable button if (!activeViewport || !$(activeViewport).find('canvas').length) { return true; } // Get images in the stack var stackToolData = cornerstoneTools.getToolState(activeViewport, 'stack'); // No images in the stack, so disable button if (!stackToolData || !stackToolData.data || !stackToolData.data.length) { return true; } // Get number of images in the stack var stackData = stackToolData.data[0]; var nImages = stackData.imageIds && stackData.imageIds.length ? stackData.imageIds.length : 1; // Stack has just one image, so disable button if (nImages === 1) { return true; } return false; }; // Stop clips on all non-empty elements var stopAllClips = function () { var elements = $('.imageViewerViewport').not('.empty'); elements.each(function (index, element) { if ($(element).find('canvas').length) { cornerstoneTools.stopClip(element); } }); }; var stopActiveClip = function () { var activeElement = getActiveViewportElement(); if ($(activeElement).find('canvas').length) { cornerstoneTools.stopClip(activeElement); } }; var isStackScrollLinkingDisabled = function () { var linkableViewportsCount = 0; // Its called everytime active viewport and/or layout change Session.get('activeViewport'); Session.get('LayoutManagerUpdated'); var synchronizer = OHIF.viewer.stackImagePositionOffsetSynchronizer; if (synchronizer) { var linkableViewports = synchronizer.getLinkableViewports(); linkableViewportsCount = linkableViewports.length; } return linkableViewportsCount <= 1; }; var isStackScrollLinkingActive = function () { var isActive = true; // Its called everytime active viewport layout changes Session.get('LayoutManagerUpdated'); var synchronizer = OHIF.viewer.stackImagePositionOffsetSynchronizer; if (!synchronizer) { return; } var syncedElements = _.pluck(synchronizer.syncedViewports, 'element'); var $renderedViewports = $('.imageViewerViewport'); $renderedViewports.each(function (index, element) { if (!_.contains(syncedElements, element)) { isActive = false; } }); return isActive; }; // Create an event listener to update playing state when a clip stops playing window.addEventListener('cornerstonetoolsclipstopped', function () { Session.set('UpdateCINE', Math.random()); }); /** * Export functions inside viewportUtils namespace. */ var viewportUtils = { getEnabledElementForActiveElement: getEnabledElementForActiveElement, getEnabledElement: getEnabledElement, getActiveViewportElement: getActiveViewportElement, zoomIn: zoomIn, zoomOut: zoomOut, zoomToFit: zoomToFit, rotateL: rotateL, rotateR: rotateR, invert: invert, flipV: flipV, flipH: flipH, resetViewport: resetViewport, clearTools: clearTools, linkStackScroll: linkStackScroll, toggleDialog: toggleDialog, toggleCinePlay: toggleCinePlay, toggleCineDialog: toggleCineDialog, toggleDownloadDialog: toggleDownloadDialog, isPlaying: isPlaying, isDownloadEnabled: isDownloadEnabled, hasMultipleFrames: hasMultipleFrames, stopAllClips: stopAllClips, isStackScrollLinkingDisabled: isStackScrollLinkingDisabled, isStackScrollLinkingActive: isStackScrollLinkingActive }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"classes":{"ImageSet.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/ImageSet.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); module.export({ ImageSet: function () { return ImageSet; } }); var Random; module.watch(require("meteor/random"), { Random: function (v) { Random = v; } }, 0); var OHIFError; module.watch(require("./OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 1); var OBJECT = 'object'; /** * This class defines an ImageSet object which will be used across the viewer. This object represents * a list of images that are associated by any arbitrary criteria being thus content agnostic. Besides the * main attributes (images and uid) it allows additional attributes to be appended to it (currently * indiscriminately, but this should be changed). */ var ImageSet = /*#__PURE__*/ function () { function ImageSet(images) { if (Array.isArray(images) !== true) { throw new OHIFError('ImageSet expects an array of images'); } // @property "images" Object.defineProperty(this, 'images', { enumerable: false, configurable: false, writable: false, value: images }); // @property "uid" Object.defineProperty(this, 'uid', { enumerable: false, configurable: false, writable: false, value: Random.id() // Unique ID of the instance }); } var _proto = ImageSet.prototype; _proto.getUID = function () { function getUID() { return this.uid; } return getUID; }(); _proto.setAttribute = function () { function setAttribute(attribute, value) { this[attribute] = value; } return setAttribute; }(); _proto.getAttribute = function () { function getAttribute(attribute) { return this[attribute]; } return getAttribute; }(); _proto.setAttributes = function () { function setAttributes(attributes) { if ((0, _typeof2.default)(attributes) === OBJECT && attributes !== null) { var imageSet = this, hasOwn = Object.prototype.hasOwnProperty; for (var attribute in meteorBabelHelpers.sanitizeForInObject(attributes)) { if (hasOwn.call(attributes, attribute)) { imageSet[attribute] = attributes[attribute]; } } } } return setAttributes; }(); _proto.getImage = function () { function getImage(index) { return this.images[index]; } return getImage; }(); _proto.sortBy = function () { function sortBy(sortingCallback) { return this.images.sort(sortingCallback); } return sortBy; }(); return ImageSet; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"LayoutManager.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/LayoutManager.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ LayoutManager: function () { return LayoutManager; } }); var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 1); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 2); var Tracker; module.watch(require("meteor/tracker"), { Tracker: function (v) { Tracker = v; } }, 3); var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 4); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 5); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 6); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 7); var PLUGIN_CORNERSTONE = 'cornerstone'; var isInteractingWithViewport = false; Meteor.startup(function () { var setInteracting = function (flag) { isInteractingWithViewport = flag; }; var $body = $('body'); $body.on('mousedown', '.imageViewerViewport', function () { return setInteracting(true); }); $body.on('mouseup', function () { return setInteracting(false); }); }); // Displays Series in Viewports given a Protocol and list of Studies var LayoutManager = /*#__PURE__*/ function () { /** * Constructor: initializes a Layout Manager object. * @param {DOM element} parentNode DOM element representing the parent node, which wraps the Layout Manager content * @param {Array} studies Array of studies objects that will be rendered in the Viewer. Each object will be rendered in a div.imageViewerViewport */ function LayoutManager(parentNode, studies) { var _this = this; OHIF.log.info('LayoutManager constructor'); this.observer = new Tracker.Dependency(); this.parentNode = parentNode; this.studies = studies; this.viewportData = []; this.layoutTemplateName = 'gridLayout'; this.layoutProps = { rows: 1, columns: 1 }; this.layoutClassName = this.getLayoutClass(); this.isZoomed = false; var updateSessionFn = function () { var random = Math.random(); Session.set('LayoutManagerUpdated', random); _this.observer.changed(); }; this.updateSession = _.throttle(updateSessionFn, 300, { leading: true, trailing: false }); } /** * Returns the number of viewports rendered, based on layoutProps * @return {integer} number of viewports */ var _proto = LayoutManager.prototype; _proto.getNumberOfViewports = function () { function getNumberOfViewports() { return this.layoutProps.rows * this.layoutProps.columns; } return getNumberOfViewports; }(); /** * It creates a new viewport data. This is useful for the first rendering when no viewportData is set yet. */ _proto.setDefaultViewportData = function () { function setDefaultViewportData() { OHIF.log.info('LayoutManager setDefaultViewportData'); var self = this; // Get the number of viewports to be rendered var viewportsAmount = this.getNumberOfViewports(); // Store the old viewport data and reset the current var oldViewportData = self.viewportData; // Get the studies and display sets sequence map var sequenceMap = this.getDisplaySetSequenceMap(); // Check if the display sets are sequenced var isSequenced = this.isDisplaySetsSequenced(sequenceMap); // Define the current viewport index and the viewport data array var currentViewportIndex = 0; if (viewportsAmount > oldViewportData.length && oldViewportData.length && isSequenced) { // Keep the displayed display sets self.viewportData = oldViewportData; currentViewportIndex = oldViewportData.length; } else if (viewportsAmount <= oldViewportData.length) { // Reduce the original displayed display sets self.viewportData = oldViewportData.slice(0, viewportsAmount); return; } else { // Reset all display sets self.viewportData = []; } // Get all the display sets for the viewer studies var displaySets = []; this.studies.forEach(function (study) { study.displaySets.forEach(function (dSet) { return dSet.images.length && displaySets.push(dSet); }); }); // Get the display sets that will be appended to the current ones var appendix; var currentLength = self.viewportData.length; if (currentLength) { // TODO: isolate displaySets array by study (maybe a map?) var beginIndex = sequenceMap.values().next().value[0].displaySetIndex + currentLength; var endIndex = beginIndex + (viewportsAmount - currentLength); appendix = displaySets.slice(beginIndex, endIndex); } else { // Get available display sets from the first to the grid size appendix = displaySets.slice(0, viewportsAmount); } // Generate the additional data based on the appendix var additionalData = []; appendix.forEach(function (displaySet, index) { var images = displaySet.images, studyInstanceUid = displaySet.studyInstanceUid, seriesInstanceUid = displaySet.seriesInstanceUid, displaySetInstanceUid = displaySet.displaySetInstanceUid; var sopInstanceUid = images[0] && images[0].getSOPInstanceUID ? images[0].getSOPInstanceUID() : ''; var viewportIndex = currentViewportIndex + index; var data = { viewportIndex: viewportIndex, studyInstanceUid: studyInstanceUid, seriesInstanceUid: seriesInstanceUid, displaySetInstanceUid: displaySetInstanceUid, sopInstanceUid: sopInstanceUid, plugin: PLUGIN_CORNERSTONE }; additionalData.push(data); }); // Append the additional data with the viewport data self.viewportData = self.viewportData.concat(additionalData); // Push empty objects if the amount is lesser than the grid size while (self.viewportData.length < viewportsAmount) { self.viewportData.push({}); } } return setDefaultViewportData; }(); /** * Returns the name of the class to be added to the parentNode * @return {string} class name following the pattern layout--. Ex: layout-1-1, layout-2-2 */ _proto.getLayoutClass = function () { function getLayoutClass() { var _this$layoutProps = this.layoutProps, rows = _this$layoutProps.rows, columns = _this$layoutProps.columns; var layoutClass = "layout-" + rows + "-" + columns; return layoutClass; } return getLayoutClass; }(); /** * Add a class to the parentNode based on the layout configuration. * This function is helpful to style the layout of viewports. * Besides that, each inner div.viewportContainer will have helpful classes * as well. See viewer/components/gridLayout/ component in this ohif-viewerbase package. */ _proto.updateLayoutClass = function () { function updateLayoutClass() { var newLayoutClass = this.getLayoutClass(); // If layout has changed, change its class if (this.layoutClassName !== newLayoutClass) { this.parentNode.classList.remove(this.layoutClassName); } this.layoutClassName = newLayoutClass; this.parentNode.classList.add(newLayoutClass); } return updateLayoutClass; }(); /** * Updates the grid with the new layout props. * It iterates over all viewportData to render the studies * in the viewports. * If no viewportData or no viewports defined, it renders the default viewport data. */ _proto.updateViewports = function () { function updateViewports() { OHIF.log.info('LayoutManager updateViewports'); if (!this.viewportData || !this.viewportData.length || this.viewportData.length !== this.getNumberOfViewports()) { this.setDefaultViewportData(); } this.viewportData.forEach(function (data) { if (!data.plugin) { data.plugin = PLUGIN_CORNERSTONE; } }); // imageViewerViewports occasionally needs relevant layout data in order to set // the element style of the viewport in question var layoutProps = this.layoutProps; var data = $.extend({ viewportData: [] }, layoutProps); this.viewportData.forEach(function (viewportData) { var viewportDataAndLayoutProps = $.extend(viewportData, layoutProps); data.viewportData.push(viewportDataAndLayoutProps); }); var layoutTemplate = Template[this.layoutTemplateName]; this.parentNode.innerHTML = ''; this.updateLayoutClass(); Blaze.renderWithData(layoutTemplate, data, this.parentNode); this.updateSession(); this.isZoomed = false; } return updateViewports; }(); /** * This function destroys and re-renders the imageViewerViewport template. * It uses the data provided to load a new display set into the produced viewport. * @param {integer} viewportIndex index of the viewport to be re-rendered * @param {Object} data instance data object */ _proto.rerenderViewportWithNewDisplaySet = function () { function rerenderViewportWithNewDisplaySet(viewportIndex, viewportData) { // Clone the data to prevent changing the original object var data = _.clone(viewportData); OHIF.log.info("LayoutManager rerenderViewportWithNewDisplaySet: " + viewportIndex); // The parent container is identified because it is later removed from the DOM var container = $('.viewportContainer').get(viewportIndex); // Record the current viewportIndex so this can be passed into the re-rendering call data.viewportIndex = viewportIndex; // If we have been provided with a plugin to use, use it. // Otherwise, use whichever plugin is currently in use in this viewport. var plugin = data.plugin || this.viewportData[viewportIndex].plugin; var pluginData = data.pluginData || this.viewportData[viewportIndex].pluginData; // Update the dictionary of loaded displaySet for the specified viewport this.viewportData[viewportIndex] = { viewportIndex: viewportIndex, displaySetInstanceUid: data.displaySetInstanceUid, seriesInstanceUid: data.seriesInstanceUid, studyInstanceUid: data.studyInstanceUid, renderedCallback: data.renderedCallback, currentImageIdIndex: data.currentImageIdIndex || 0, plugin: plugin, pluginData: pluginData }; var newViewportContainer = document.createElement('div'); // Render and insert the template if (plugin === PLUGIN_CORNERSTONE) { // Remove the hover styling var element = $(container).find('.imageViewerViewport'); element.find('canvas').not('.magnifyTool').removeClass('faded'); // Remove the whole template, add in the new one var viewportContainer = element.parents('.removable'); newViewportContainer.className = 'removable'; // Remove the parent element of the template // This is a workaround since otherwise Blaze UI onDestroyed doesn't fire viewportContainer.remove(); container.appendChild(newViewportContainer); Blaze.renderWithData(Template.imageViewerViewport, data, newViewportContainer); } else { newViewportContainer.className = "viewport-plugin-" + plugin; newViewportContainer.style.width = '100%'; newViewportContainer.style.height = '100%'; container.innerHTML = ''; container.appendChild(newViewportContainer); } this.updateSession(); } return rerenderViewportWithNewDisplaySet; }(); /** * Enlarge a single viewport. Useful when the layout has more than one viewport * @param {integer} viewportIndex Index of the viewport to be enlarged */ _proto.enlargeViewport = function () { function enlargeViewport(viewportIndex) { OHIF.log.info("LayoutManager enlargeViewport: " + viewportIndex); if (!this.viewportData || !this.viewportData.length) { return; } // Clone the array for later this.previousViewportData = this.viewportData.slice(0); var singleViewportData = $.extend({}, this.viewportData[viewportIndex]); singleViewportData.rows = 1; singleViewportData.columns = 1; singleViewportData.viewportIndex = 0; var data = { viewportData: [singleViewportData], rows: 1, columns: 1 }; var layoutTemplate = Template.gridLayout; this.parentNode.innerHTML = ''; Blaze.renderWithData(layoutTemplate, data, this.parentNode); this.isZoomed = true; this.zoomedViewportIndex = viewportIndex; this.viewportData = data.viewportData; this.updateSession(); } return enlargeViewport; }(); /** * Resets to the previous layout configuration. * Useful after enlarging a single viewport. */ _proto.resetPreviousLayout = function () { function resetPreviousLayout() { OHIF.log.info('LayoutManager resetPreviousLayout'); if (!this.isZoomed) { return; } this.previousViewportData[this.zoomedViewportIndex] = $.extend({}, this.viewportData[0]); this.previousViewportData[this.zoomedViewportIndex].viewportIndex = this.zoomedViewportIndex; this.viewportData = this.previousViewportData; this.updateViewports(); } return resetPreviousLayout; }(); /** * Toogle viewport enlargement. * Useful for user to enlarge or going back to previous layout configurations * @param {integer} viewportIndex Index of the viewport to be toggled */ _proto.toggleEnlargement = function () { function toggleEnlargement(viewportIndex) { OHIF.log.info("LayoutManager toggleEnlargement: " + viewportIndex); if (this.isZoomed) { this.resetPreviousLayout(); } else { // Don't enlarge the viewport if we only have one Viewport // to begin with if (this.getNumberOfViewports() > 1) { this.enlargeViewport(viewportIndex); } } } return toggleEnlargement; }(); /** * Return the display sets map sequence of display sets and viewports */ _proto.getDisplaySetSequenceMap = function () { function getDisplaySetSequenceMap() { var _this2 = this; OHIF.log.info('LayoutManager getDisplaySetSequenceMap'); // Get the viewport data list var viewportDataList = this.viewportData; // Create a map to control the display set sequence var sequenceMap = new Map(); // Iterate over each viewport and register its details on the sequence map viewportDataList.forEach(function (viewportData, viewportIndex) { // Get the current study var currentStudy = _.findWhere(_this2.studies, { studyInstanceUid: viewportData.studyInstanceUid }) || _this2.studies[0]; // Get the display sets var displaySets = currentStudy.displaySets; // Get the current display set var displaySet = _.findWhere(displaySets, { displaySetInstanceUid: viewportData.displaySetInstanceUid }); // Get the current instance index (using 9999 to sort greater than -1) var displaySetIndex = _.indexOf(displaySets, displaySet); displaySetIndex = displaySetIndex < 0 ? 9999 : displaySetIndex; // Try to get a map entry for current study or create it if not present var studyViewports = sequenceMap.get(currentStudy); if (!studyViewports) { studyViewports = []; sequenceMap.set(currentStudy, studyViewports); } // Register the viewport index and the display set index on the map studyViewports.push({ viewportIndex: viewportIndex, displaySetIndex: displaySetIndex }); }); // Return the generated sequence map return sequenceMap; } return getDisplaySetSequenceMap; }(); /** * Check if all the display sets and viewports are sequenced * @param {Array} definedSequenceMap Array of display set sequence map * @return {Boolean} Returns if the display set sequence map is sequenced or not */ _proto.isDisplaySetsSequenced = function () { function isDisplaySetsSequenced(definedSequenceMap) { OHIF.log.info('LayoutManager isDisplaySetsSequenced'); var isSequenced = true; // Get the studies and display sets sequence map var sequenceMap = definedSequenceMap || this.getDisplaySetSequenceMap(); sequenceMap.forEach(function (studyViewports, study) { var lastDisplaySetIndex = null; var lastViewportIndex = null; studyViewports.forEach(function (_ref, index) { var viewportIndex = _ref.viewportIndex, displaySetIndex = _ref.displaySetIndex; // Check if the sequence is wrong if (displaySetIndex !== 9999 && lastViewportIndex !== null && lastDisplaySetIndex !== null && displaySetIndex !== null && (viewportIndex - 1 !== lastViewportIndex || displaySetIndex - 1 !== lastDisplaySetIndex)) { // Set the sequenced flag as false; isSequenced = false; } // Update the last viewport index lastViewportIndex = viewportIndex; // Update the last display set index lastDisplaySetIndex = displaySetIndex; }); }); return isSequenced; } return isDisplaySetsSequenced; }(); /** * Check if is possible to move display sets on a specific direction. * It checks if looping is allowed by OHIF.uiSettings.displaySetNavigationLoopOverSeries * @param {Boolean} isNext Represents the direction * @return {Boolean} Returns if display sets can be moved */ _proto.canMoveDisplaySets = function () { function canMoveDisplaySets(isNext) { OHIF.log.info('LayoutManager canMoveDisplaySets'); // Get the setting that defines if the display set navigation is multiple var isMultiple = OHIF.uiSettings.displaySetNavigationMultipleViewports; // Get the setting that allow display set navigation looping over series var allowLooping = OHIF.uiSettings.displaySetNavigationLoopOverSeries; // Get the studies and display sets sequence map var sequenceMap = this.getDisplaySetSequenceMap(); // Check if the display sets are sequenced var isSequenced = this.isDisplaySetsSequenced(sequenceMap); // Get Active Viewport Index if isMultiple is false var activeViewportIndex = !isMultiple ? Session.get('activeViewport') : null; // Check if is next and looping is blocked if (isNext && !allowLooping) { // Check if the end was reached var endReached = true; sequenceMap.forEach(function (studyViewports, study) { // Get active viewport index if isMultiple is false ortherwise get last var studyViewport = studyViewports[activeViewportIndex !== null ? activeViewportIndex : studyViewports.length - 1]; if (!studyViewport) { return; } var viewportIndex = studyViewport.displaySetIndex; var layoutViewports = studyViewports.length; var amount = study.displaySets.length; var move = !isMultiple ? 1 : amount % layoutViewports || layoutViewports; var lastStepIndex = amount - move; // 9999 for index means empty viewport, see getDisplaySetSequenceMap function if (viewportIndex !== 9999 && viewportIndex !== lastStepIndex) { endReached = false; } }); // Return false if end is not reached yet if ((!isMultiple || isSequenced) && endReached) { return false; } } // Check if is previous and looping is blocked if (!isNext && !allowLooping) { // Check if the begin was reached var beginReached = true; if (activeViewportIndex >= 0) { sequenceMap.forEach(function (studyViewports, study) { // Get active viewport index if isMultiple is false ortherwise get first var studyViewport = studyViewports[activeViewportIndex !== null ? activeViewportIndex : 0]; if (!studyViewport) { return; } var viewportIndex = studyViewport.displaySetIndex; var layoutViewports = studyViewports.length; // 9999 for index means empty viewport, see getDisplaySetSequenceMap function if (viewportIndex !== 9999 && viewportIndex - layoutViewports !== -layoutViewports) { beginReached = false; } }); } // Return false if begin is not reached yet if ((!isMultiple || isSequenced) && beginReached) { return false; } } return true; } return canMoveDisplaySets; }(); /** * Move display sets forward or backward in the given viewport index * @param {integer} viewportIndex Index of the viewport to be moved * @param {Boolean} isNext Represents the direction (true = forward, false = backward) */ _proto.moveSingleViewportDisplaySets = function () { function moveSingleViewportDisplaySets(viewportIndex, isNext) { OHIF.log.info("LayoutManager moveSingleViewportDisplaySets: " + viewportIndex); // Get the setting that allow display set navigation looping over series var allowLooping = OHIF.uiSettings.displaySetNavigationLoopOverSeries; // Get the selected viewport data var viewportData = this.viewportData[viewportIndex]; // Get the current study var currentStudy = _.findWhere(this.studies, { studyInstanceUid: viewportData.studyInstanceUid }) || this.studies[0]; // Get the display sets var displaySets = currentStudy.displaySets; // Get the current display set var currentDisplaySet = _.findWhere(displaySets, { displaySetInstanceUid: viewportData.displaySetInstanceUid }); // Get the new index and ensure that it will exists in display sets var newIndex = _.indexOf(displaySets, currentDisplaySet); if (isNext) { newIndex++; if (newIndex >= displaySets.length) { // Stop here if looping is not allowed if (!allowLooping) { return; } newIndex = 0; } } else { newIndex--; if (newIndex < 0) { // Stop here if looping is not allowed if (!allowLooping) { return; } newIndex = displaySets.length - 1; } } // Get the display set data for the new index var newDisplaySetData = displaySets[newIndex]; // Rerender the viewport using the new display set data this.rerenderViewportWithNewDisplaySet(viewportIndex, newDisplaySetData); } return moveSingleViewportDisplaySets; }(); /** * Move multiple display sets forward or backward in all viewports * @param {Boolean} isNext Represents the direction (true = forward, false = backward) */ _proto.moveMultipleViewportDisplaySets = function () { function moveMultipleViewportDisplaySets(isNext) { var _this3 = this; OHIF.log.info('LayoutManager moveMultipleViewportDisplaySets'); // Get the setting that allow display set navigation looping over series var allowLooping = OHIF.uiSettings.displaySetNavigationLoopOverSeries; // Create a map to control the display set sequence var sequenceMap = this.getDisplaySetSequenceMap(); // Check if the display sets are sequenced var isSequenced = this.isDisplaySetsSequenced(sequenceMap); var displaySetsToRender = []; // Iterate over the studies map and move its display sets sequenceMap.forEach(function (studyViewports, study) { // Sort the viewports on the study by the display set index studyViewports.sort(function (a, b) { return a.displaySetIndex > b.displaySetIndex; }); // Get the study display sets var displaySets = study.displaySets; // Calculate the base index var firstIndex = studyViewports[0].displaySetIndex; var steps = studyViewports.length; var rest = firstIndex % steps; var baseIndex = rest ? firstIndex - rest : firstIndex; var direction = isNext ? 1 : -1; baseIndex += steps * direction; var amount = displaySets.length; // Check if the indexes are sequenced or will overflow the array bounds if (baseIndex >= amount) { var move = amount % steps || steps; var lastStepIndex = amount - move; if (firstIndex + steps !== lastStepIndex + steps) { // Reset the index if the display sets are sequenced but shifted baseIndex = lastStepIndex; } else if (!allowLooping) { // Stop here if looping is not allowed return; } else { // Start over the series if looping is allowed baseIndex = 0; } } else if (baseIndex < 0) { if (firstIndex > 0) { // Reset the index if the display sets are sequenced but shifted baseIndex = 0; } else if (!allowLooping) { // Stop here if looping is not allowed return; } else { // Go to the series' end if looping is allowed baseIndex = amount - 1 - (amount - 1) % steps; } } else if (!isSequenced) { // Reset the sequence if indexes are not sequenced baseIndex = 0; } // Iterate over the current study viewports studyViewports.forEach(function (_ref2, index) { var viewportIndex = _ref2.viewportIndex; // Get the new displaySet index to be rendered in viewport var newIndex = baseIndex + index; // Get the display set data for the new index var displaySetData = displaySets[newIndex] || {}; // Add the current display set that on the render list displaySetsToRender.push(displaySetData); }); }); // Sort the display sets var sortingFunction = OHIF.utils.sortBy({ name: 'studyInstanceUid' }, { name: 'instanceNumber' }, { name: 'seriesNumber' }); displaySetsToRender.sort(function (a, b) { return sortingFunction(a, b); }); // Iterate over each display set data and render on its respective viewport displaySetsToRender.forEach(function (data, index) { _this3.rerenderViewportWithNewDisplaySet(index, data); }); } return moveMultipleViewportDisplaySets; }(); /** * Move display sets forward or backward * @param {Boolean} isNext Represents the direction (true = forward, false = backward) */ _proto.moveDisplaySets = function () { function moveDisplaySets(isNext) { // Prevent display sets navigation while interacting with any cornerstone tool if (isInteractingWithViewport) return; OHIF.log.info('LayoutManager moveDisplaySets'); //Check if navigation is on a single or multiple viewports if (OHIF.uiSettings.displaySetNavigationMultipleViewports) { // Move display sets on multiple viewports this.moveMultipleViewportDisplaySets(isNext); } else { // Get the selected viewport index var viewportIndex = Session.get('activeViewport'); // Move display sets on a single viewport this.moveSingleViewportDisplaySets(viewportIndex, isNext); } } return moveDisplaySets; }(); /** * Check if a study is loaded into a viewport * @param {string} studyInstanceUid Study instance Uid string * @param {integer} viewportIndex Index of the viewport to be checked * @return {Boolean} Returns if the given study is in the given viewport or not */ _proto.isStudyLoadedIntoViewport = function () { function isStudyLoadedIntoViewport(studyInstanceUid, viewportIndex) { return this.viewportData.find(function (item) { return item.studyInstanceUid === studyInstanceUid && item.viewportIndex === viewportIndex; }) !== void 0; } return isStudyLoadedIntoViewport; }(); /** * Check if the layout has multiple rows and columns * @return {Boolean} Return if the layout has multiple rows and columns or not */ _proto.isMultipleLayout = function () { function isMultipleLayout() { return this.layoutProps.row !== 1 && this.layoutProps.columns !== 1; } return isMultipleLayout; }(); return LayoutManager; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"OHIFError.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/OHIFError.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); var _wrapNativeSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/wrapNativeSuper")); module.export({ OHIFError: function () { return OHIFError; } }); var OHIFError = /*#__PURE__*/ function (_Error) { (0, _inheritsLoose2.default)(OHIFError, _Error); function OHIFError(message) { var _this; _this = _Error.call(this) || this; _this.message = message; _this.stack = new Error().stack; _this.name = _this.constructor.name; return _this; } return OHIFError; }((0, _wrapNativeSuper2.default)(Error)); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"ResizeViewportManager.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/ResizeViewportManager.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ ResizeViewportManager: function () { return ResizeViewportManager; } }); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 0); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 1); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 2); var getInstanceClassDefaultViewport; module.watch(require("../instanceClassSpecificViewport"), { getInstanceClassDefaultViewport: function (v) { getInstanceClassDefaultViewport = v; } }, 3); var ResizeViewportManager = /*#__PURE__*/ function () { function ResizeViewportManager() { this._resizeHandler = null; } // Reposition Study Series Quick Switch based whether side bars are opened or not var _proto = ResizeViewportManager.prototype; _proto.repositionStudySeriesQuickSwitch = function () { function repositionStudySeriesQuickSwitch() { OHIF.log.info('ResizeViewportManager repositionStudySeriesQuickSwitch'); // Stop here if viewer is not displayed var isViewer = Session.get('ViewerOpened'); if (!isViewer) return; // Stop here if there is no one or only one viewport var nViewports = OHIF.viewerbase.layoutManager.viewportData.length; if (!nViewports || nViewports <= 1) return; var $viewer = $('#viewer'); var leftSidebar = $viewer.find('.sidebar-left.sidebar-open'); var rightSidebar = $viewer.find('.sidebar-right.sidebar-open'); var $leftQuickSwitch = $('.quickSwitchWrapper.left'); var $rightQuickSwitch = $('.quickSwitchWrapper.right'); var hasLeftSidebar = leftSidebar.length > 0; var hasRightSidebar = rightSidebar.length > 0; $rightQuickSwitch.removeClass('left-sidebar-only'); $leftQuickSwitch.removeClass('right-sidebar-only'); var leftOffset = 0; if (hasLeftSidebar) { leftOffset = leftSidebar.width() / $(window).width() * 100; if (!hasRightSidebar) { $rightQuickSwitch.addClass('left-sidebar-only'); } } if (hasRightSidebar && !hasLeftSidebar) { $leftQuickSwitch.addClass('right-sidebar-only'); } var leftPosition = $('#imageViewerViewports').width() / nViewports / $(window).width() * 100 + leftOffset; var rightPosition = 100 - leftPosition; $leftQuickSwitch.css('right', rightPosition + '%'); $rightQuickSwitch.css('left', leftPosition + '%'); } return repositionStudySeriesQuickSwitch; }(); // Relocate dialogs positions _proto.relocateDialogs = function () { function relocateDialogs() { OHIF.log.info('ResizeViewportManager relocateDialogs'); var $bottomRightDialogs = $('#annotationDialog, #textMarkerOptionsDialog'); $bottomRightDialogs.css({ top: '', // This removes the CSS property completely left: '', bottom: 0, right: 0 }); var centerDialogs = $('.draggableDialog').not($bottomRightDialogs); centerDialogs.css({ top: 0, left: 0, bottom: 0, right: 0 }); } return relocateDialogs; }(); // Resize viewport scrollbars _proto.resizeScrollbars = function () { function resizeScrollbars(element) { OHIF.log.info('ResizeViewportManager resizeScrollbars'); var $currentOverlay = $(element).siblings('.imageViewerViewportOverlay'); $currentOverlay.find('.scrollbar').trigger('rescale'); } return resizeScrollbars; }(); // Resize a single viewport element _proto.resizeViewportElement = function () { function resizeViewportElement(element) { var fitToWindow = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var enabledElement; try { enabledElement = cornerstone.getEnabledElement(element); } catch (error) { return; } cornerstone.resize(element, fitToWindow); if (enabledElement.fitToWindow === false) { var imageId = enabledElement.image.imageId; var instance = cornerstone.metaData.get('instance', imageId); var instanceClassViewport = getInstanceClassDefaultViewport(instance, enabledElement, imageId); cornerstone.setViewport(element, instanceClassViewport); } } return resizeViewportElement; }(); // Resize each viewport element _proto.resizeViewportElements = function () { function resizeViewportElements() { var _this = this; this.relocateDialogs(); setTimeout(function () { _this.repositionStudySeriesQuickSwitch(); var elements = $('.imageViewerViewport').not('.empty'); elements.each(function (index, element) { _this.resizeViewportElement(element); _this.resizeScrollbars(element); }); }, 1); } return resizeViewportElements; }(); // Function to override resizeViewportElements function _proto.setResizeViewportElement = function () { function setResizeViewportElement(resizeViewportElements) { this.resizeViewportElements = resizeViewportElements; } return setResizeViewportElement; }(); // Avoid doing DOM manipulation during the resize handler // because it is fired very often. // Resizing is therefore performed 100 ms after the resize event stops. _proto.handleResize = function () { function handleResize() { var _this2 = this; clearTimeout(this.resizeTimer); this.resizeTimer = setTimeout(function () { OHIF.log.info('ResizeViewportManager resizeViewportElements'); _this2.resizeViewportElements(); }, 100); } return handleResize; }(); /** * Returns a unique event handler function associated with a given instance using lazy assignment. * @return {function} Returns a unique copy of the event handler of this class. */ _proto.getResizeHandler = function () { function getResizeHandler() { var resizeHandler = this._resizeHandler; if (resizeHandler === null) { resizeHandler = this.handleResize.bind(this); this._resizeHandler = resizeHandler; } return resizeHandler; } return getResizeHandler; }(); return ResizeViewportManager; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"StackImagePositionOffsetSynchronizer.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/StackImagePositionOffsetSynchronizer.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); module.export({ StackImagePositionOffsetSynchronizer: function () { return StackImagePositionOffsetSynchronizer; } }); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 0); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 1); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 2); var cornerstone, cornerstoneTools; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; }, cornerstoneTools: function (v) { cornerstoneTools = v; } }, 3); var toolManager; module.watch(require("../toolManager"), { toolManager: function (v) { toolManager = v; } }, 4); var StackImagePositionOffsetSynchronizer = /*#__PURE__*/ function () { function StackImagePositionOffsetSynchronizer() { this.active = false; this.syncedViewports = []; this.synchronizer = new cornerstoneTools.Synchronizer('cornerstonenewimage', cornerstoneTools.stackImagePositionOffsetSynchronizer); } var _proto = StackImagePositionOffsetSynchronizer.prototype; _proto.isActive = function () { function isActive() { return this.active; } return isActive; }(); _proto.activate = function () { function activate() { var viewports = this.getLinkableViewports(); this.syncViewports(viewports); } return activate; }(); _proto.activateByViewportIndexes = function () { function activateByViewportIndexes(viewportIndexes) { var viewports = this.getViewportByIndexes(viewportIndexes); this.syncViewports(viewports); } return activateByViewportIndexes; }(); _proto.deactivate = function () { function deactivate() { if (!this.isActive()) { return; } while (this.syncedViewports.length) { var viewport = this.syncedViewports[0]; this.removeViewport(viewport); } this.active = false; toolManager.deactivateCommandButton('linkStackScroll'); } return deactivate; }(); _proto.update = function () { function update() { if (!this.isActive()) { return; } var activeViewportElement = this.getActiveViewportElement(); if (this.isViewportSynced(activeViewportElement)) { return; } this.deactivate(); this.activate(); } return update; }(); _proto.syncViewports = function () { function syncViewports(viewports) { var _this = this; var viewportIndexes = []; if (this.isActive() || viewports.length <= 1) { return; } viewports.forEach(function (viewport, index) { _this.synchronizer.add(viewport.element); _this.syncedViewports.push(viewport); viewportIndexes.push(viewport.index); if (!_this.disabledListener) { _this.disabledListener = _this.elementDisabledHandler(_this); } viewport.element.addEventListener(StackImagePositionOffsetSynchronizer.ELEMENT_DISABLED_EVENT, _this.disabledListener); }); this.active = true; toolManager.activateCommandButton('linkStackScroll'); Session.set('StackImagePositionOffsetSynchronizerLinkedViewports', viewportIndexes); } return syncViewports; }(); _proto.isViewportSynced = function () { function isViewportSynced(viewportElement) { return !!this.getViewportByElement(viewportElement); } return isViewportSynced; }(); _proto.getActiveViewportElement = function () { function getActiveViewportElement() { var viewportIndex = Session.get('activeViewport') || 0; return $('.imageViewerViewport').get(viewportIndex); } return getActiveViewportElement; }(); _proto.removeViewport = function () { function removeViewport(viewport) { var index = this.syncedViewports.indexOf(viewport); if (index === -1) { return; } this.syncedViewports.splice(index, 1); this.synchronizer.remove(viewport.element); this.removeLinkedViewportFromSession(viewport); viewport.element.removeEventListener(StackImagePositionOffsetSynchronizer.ELEMENT_DISABLED_EVENT, this.disabledListener); } return removeViewport; }(); _proto.getViewportByElement = function () { function getViewportByElement(viewportElement) { var length = this.syncedViewports.length; for (var i = 0; i < length; i++) { var viewport = this.syncedViewports[i]; if (viewport.element === viewportElement) { return viewport; } } } return getViewportByElement; }(); _proto.removeViewportByElement = function () { function removeViewportByElement(viewportElement) { var viewport = this.getViewportByElement(viewportElement); if (viewport) { this.removeViewport(viewport); } } return removeViewportByElement; }(); _proto.removeLinkedViewportFromSession = function () { function removeLinkedViewportFromSession(viewport) { var linkedViewports = Session.get('StackImagePositionOffsetSynchronizerLinkedViewports'); var index = linkedViewports.indexOf(viewport.index); if (index !== -1) { linkedViewports.splice(index, 1); Session.set('StackImagePositionOffsetSynchronizerLinkedViewports', linkedViewports); } } return removeLinkedViewportFromSession; }(); _proto.elementDisabledHandler = function () { function elementDisabledHandler(context) { return function (e) { return context.removeViewportByElement(e.detail.element); }; } return elementDisabledHandler; }(); _proto.getViewportByIndexes = function () { function getViewportByIndexes(viewportIndexes) { var viewports = []; var $viewportElements = $('.imageViewerViewport'); viewportIndexes.forEach(function (index) { var element = $viewportElements.get(index); if (!element) { return; } viewports.push({ index: index, element: element }); }); return viewports; } return getViewportByIndexes; }(); _proto.isViewportsLinkable = function () { function isViewportsLinkable(viewportElementA, viewportElementB) { var viewportAImageNormal = this.getViewportImageNormal(viewportElementA); var viewportBImageNormal = this.getViewportImageNormal(viewportElementB); if (viewportAImageNormal && viewportBImageNormal) { var angleInRadians = viewportBImageNormal.angleTo(viewportAImageNormal); // Pi / 12 radians = 15 degrees // If the angle between two vectors is Pi, it means they are just inverted return angleInRadians < Math.PI / 12 || angleInRadians === Math.PI; } return false; } return isViewportsLinkable; }(); _proto.getLinkableViewports = function () { function getLinkableViewports() { var _this2 = this; var activeViewportElement = this.getActiveViewportElement(); var viewports = []; $('.imageViewerViewport').each(function (index, viewportElement) { if (_this2.isViewportsLinkable(activeViewportElement, viewportElement)) { viewports.push({ index: index, element: viewportElement }); } }); return viewports; } return getLinkableViewports; }(); _proto.getViewportImageNormal = function () { function getViewportImageNormal(element) { if (!element) { return; } element = $(element).get(0); try { var enabledElement = cornerstone.getEnabledElement(element); if (!enabledElement.image) { return; } var imageId = enabledElement.image.imageId; var imagePlane = cornerstone.metaData.get('imagePlane', imageId); if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) { return; } return imagePlane.rowCosines.clone().cross(imagePlane.columnCosines); } catch (error) { var errorMessage = error.message || error; OHIF.log.info("StackImagePositionOffsetSynchronizer getViewportImageNormal: " + errorMessage); } } return getViewportImageNormal; }(); (0, _createClass2.default)(StackImagePositionOffsetSynchronizer, null, [{ key: "ELEMENT_DISABLED_EVENT", get: function () { return 'cornerstoneelementdisabled.StackImagePositionOffsetSynchronizer'; } }]); return StackImagePositionOffsetSynchronizer; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"StudyLoadingListener.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/StudyLoadingListener.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); module.export({ StudyLoadingListener: function () { return StudyLoadingListener; }, StackLoadingListener: function () { return StackLoadingListener; }, DICOMFileLoadingListener: function () { return DICOMFileLoadingListener; } }); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 0); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 1); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 2); var cornerstone, cornerstoneWADOImageLoader; module.watch(require("meteor/ohif:cornerstone"), { cornerstone: function (v) { cornerstone = v; }, cornerstoneWADOImageLoader: function (v) { cornerstoneWADOImageLoader = v; } }, 3); var BaseLoadingListener = /*#__PURE__*/ function () { function BaseLoadingListener(stack, options) { options = options || {}; this.id = BaseLoadingListener.getNewId(); this.stack = stack; this.startListening(); this.statsItemsLimit = options.statsItemsLimit || 2; this.stats = { items: [], total: 0, elapsedTime: 0, speed: 0 }; // Register the start point to make it possible to calculate // bytes/s or frames/s when the first byte or frame is received this._addStatsData(0); // Update the progress before starting the download // to make it possible to update the UI this._updateProgress(); } var _proto = BaseLoadingListener.prototype; _proto._addStatsData = function () { function _addStatsData(value) { var date = new Date(); var stats = this.stats; var items = stats.items; var newItem = { value: value, date: date }; items.push(newItem); stats.total += newItem.value; // Remove items until it gets below the limit while (items.length > this.statsItemsLimit) { var item = items.shift(); stats.total -= item.value; } // Update the elapsedTime (seconds) based on first and last // elements and recalculate the speed (bytes/s or frames/s) if (items.length > 1) { var oldestItem = items[0]; stats.elapsedTime = (newItem.date.getTime() - oldestItem.date.getTime()) / 1000; stats.speed = (stats.total - oldestItem.value) / stats.elapsedTime; } } return _addStatsData; }(); _proto._getProgressSessionId = function () { function _getProgressSessionId() { var displaySetInstanceUid = this.stack.displaySetInstanceUid; return 'StackProgress:' + displaySetInstanceUid; } return _getProgressSessionId; }(); _proto._clearSession = function () { function _clearSession() { var progressSessionId = this._getProgressSessionId(); Session.set(progressSessionId, undefined); delete Session.keys.progressSessionId; } return _clearSession; }(); _proto.startListening = function () { function startListening() { throw new Error('`startListening` must be implemented by child clases'); } return startListening; }(); _proto.stopListening = function () { function stopListening() { throw new Error('`stopListening` must be implemented by child clases'); } return stopListening; }(); _proto.destroy = function () { function destroy() { this.stopListening(); this._clearSession(); } return destroy; }(); BaseLoadingListener.getNewId = function () { function getNewId() { var timeSlice = new Date().getTime().toString().slice(-8); var randomNumber = parseInt(Math.random() * 1000000000); return timeSlice.toString() + randomNumber.toString(); } return getNewId; }(); return BaseLoadingListener; }(); var DICOMFileLoadingListener = /*#__PURE__*/ function (_BaseLoadingListener) { (0, _inheritsLoose2.default)(DICOMFileLoadingListener, _BaseLoadingListener); function DICOMFileLoadingListener(stack) { var _this; _this = _BaseLoadingListener.call(this, stack) || this; _this._dataSetUrl = _this._getDataSetUrl(stack); _this._lastLoaded = 0; // Check how many instances has already been download (cached) _this._checkCachedData(); return _this; } var _proto2 = DICOMFileLoadingListener.prototype; _proto2._checkCachedData = function () { function _checkCachedData() { var dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(this._dataSetUrl); if (dataSet) { var dataSetLength = dataSet.byteArray.length; this._updateProgress({ percentComplete: 100, loaded: dataSetLength, total: dataSetLength }); } } return _checkCachedData; }(); _proto2._getImageLoadProgressEventName = function () { function _getImageLoadProgressEventName() { return 'cornerstoneimageloadprogress.' + this.id; } return _getImageLoadProgressEventName; }(); _proto2.startListening = function () { function startListening() { var imageLoadProgressEventName = this._getImageLoadProgressEventName(); var imageLoadProgressEventHandle = this._imageLoadProgressEventHandle.bind(this); this.stopListening(); cornerstone.events.addEventListener(imageLoadProgressEventName, imageLoadProgressEventHandle); } return startListening; }(); _proto2.stopListening = function () { function stopListening() { var imageLoadProgressEventName = this._getImageLoadProgressEventName(); cornerstone.events.removeEventListener(imageLoadProgressEventName); } return stopListening; }(); _proto2._imageLoadProgressEventHandle = function () { function _imageLoadProgressEventHandle(e) { var eventData = e.detail; var dataSetUrl = this._convertImageIdToDataSetUrl(eventData.imageId); var bytesDiff = eventData.loaded - this._lastLoaded; if (!this._dataSetUrl === dataSetUrl) { return; } // Add the bytes downloaded to the stats this._addStatsData(bytesDiff); // Update the download progress this._updateProgress(eventData); // Cache the last eventData.loaded value this._lastLoaded = eventData.loaded; } return _imageLoadProgressEventHandle; }(); _proto2._updateProgress = function () { function _updateProgress(eventData) { var progressSessionId = this._getProgressSessionId(); eventData = eventData || {}; Session.set(progressSessionId, { multiFrame: false, percentComplete: eventData.percentComplete, bytesLoaded: eventData.loaded, bytesTotal: eventData.total, bytesPerSecond: this.stats.speed }); } return _updateProgress; }(); _proto2._convertImageIdToDataSetUrl = function () { function _convertImageIdToDataSetUrl(imageId) { // Remove the prefix ("dicomweb:" or "wadouri:"") imageId = imageId.replace(/^(dicomweb:|wadouri:)/i, ''); // Remove "frame=999&" from the imageId imageId = imageId.replace(/frame=\d+&?/i, ''); // Remove the last "&" like in "http://...?foo=1&bar=2&" imageId = imageId.replace(/&$/, ''); return imageId; } return _convertImageIdToDataSetUrl; }(); _proto2._getDataSetUrl = function () { function _getDataSetUrl(stack) { var imageId = stack.imageIds[0]; return this._convertImageIdToDataSetUrl(imageId); } return _getDataSetUrl; }(); return DICOMFileLoadingListener; }(BaseLoadingListener); var StackLoadingListener = /*#__PURE__*/ function (_BaseLoadingListener2) { (0, _inheritsLoose2.default)(StackLoadingListener, _BaseLoadingListener2); function StackLoadingListener(stack) { var _this2; _this2 = _BaseLoadingListener2.call(this, stack, { statsItemsLimit: 20 }) || this; _this2.imageDataMap = _this2._convertImageIdsArrayToMap(stack.imageIds); _this2.framesStatus = _this2._createArray(stack.imageIds.length, false); _this2.loadedCount = 0; // Check how many instances has already been download (cached) _this2._checkCachedData(); return _this2; } var _proto3 = StackLoadingListener.prototype; _proto3._convertImageIdsArrayToMap = function () { function _convertImageIdsArrayToMap(imageIds) { var imageIdsMap = new Map(); for (var i = 0; i < imageIds.length; i++) { imageIdsMap.set(imageIds[i], { index: i, loaded: false }); } return imageIdsMap; } return _convertImageIdsArrayToMap; }(); _proto3._createArray = function () { function _createArray(length, defaultValue) { // `new Array(length)` is an anti-pattern in javascript because its // funny API. Otherwise I would go for `new Array(length).fill(false)` var array = []; for (var i = 0; i < length; i++) { array[i] = defaultValue; } return array; } return _createArray; }(); _proto3._checkCachedData = function () { function _checkCachedData() {// const imageIds = this.stack.imageIds; // TODO: No way to check status of Promise. /*for(let i = 0; i < imageIds.length; i++) { const imageId = imageIds[i]; const imagePromise = cornerstone.imageCache.getImageLoadObject(imageId).promise; if (imagePromise && (imagePromise.state() === 'resolved')) { this._updateFrameStatus(imageId, true); } }*/ } return _checkCachedData; }(); _proto3._getImageLoadedEventName = function () { function _getImageLoadedEventName() { return 'cornerstoneimageloaded.' + this.id; } return _getImageLoadedEventName; }(); _proto3._getImageCachePromiseRemoveEventName = function () { function _getImageCachePromiseRemoveEventName() { return 'cornerstoneimagecachepromiseremoved.' + this.id; } return _getImageCachePromiseRemoveEventName; }(); _proto3.startListening = function () { function startListening() { var imageLoadedEventName = this._getImageLoadedEventName(); var imageCachePromiseRemovedEventName = this._getImageCachePromiseRemoveEventName(); var imageLoadedEventHandle = this._imageLoadedEventHandle.bind(this); var imageCachePromiseRemovedEventHandle = this._imageCachePromiseRemovedEventHandle.bind(this); this.stopListening(); cornerstone.events.addEventListener(imageLoadedEventName, imageLoadedEventHandle); cornerstone.events.addEventListener(imageCachePromiseRemovedEventName, imageCachePromiseRemovedEventHandle); } return startListening; }(); _proto3.stopListening = function () { function stopListening() { var imageLoadedEventName = this._getImageLoadedEventName(); var imageCachePromiseRemovedEventName = this._getImageCachePromiseRemoveEventName(); cornerstone.events.removeEventListener(imageLoadedEventName); cornerstone.events.removeEventListener(imageCachePromiseRemovedEventName); } return stopListening; }(); _proto3._updateFrameStatus = function () { function _updateFrameStatus(imageId, loaded) { var imageData = this.imageDataMap.get(imageId); if (!imageData || imageData.loaded === loaded) { return; } // Add one more frame to the stats if (loaded) { this._addStatsData(1); } imageData.loaded = loaded; this.framesStatus[imageData.index] = loaded; this.loadedCount += loaded ? 1 : -1; this._updateProgress(); } return _updateFrameStatus; }(); _proto3._imageLoadedEventHandle = function () { function _imageLoadedEventHandle(e) { this._updateFrameStatus(e.detail.image.imageId, true); } return _imageLoadedEventHandle; }(); _proto3._imageCachePromiseRemovedEventHandle = function () { function _imageCachePromiseRemovedEventHandle(e) { this._updateFrameStatus(e.detail.imageId, false); } return _imageCachePromiseRemovedEventHandle; }(); _proto3._updateProgress = function () { function _updateProgress() { var totalFramesCount = this.stack.imageIds.length; var loadedFramesCount = this.loadedCount; var loadingFramesCount = totalFramesCount - loadedFramesCount; var percentComplete = Math.round(loadedFramesCount / totalFramesCount * 100); var progressSessionId = this._getProgressSessionId(); Session.set(progressSessionId, { multiFrame: true, totalFramesCount: totalFramesCount, loadedFramesCount: loadedFramesCount, loadingFramesCount: loadingFramesCount, percentComplete: percentComplete, framesPerSecond: this.stats.speed, framesStatus: this.framesStatus }); } return _updateProgress; }(); _proto3._logProgress = function () { function _logProgress() { var totalFramesCount = this.stack.imageIds.length; var displaySetInstanceUid = this.stack.displaySetInstanceUid; var progressBar = '['; for (var i = 0; i < totalFramesCount; i++) { var ch = this.framesStatus[i] ? '|' : '.'; progressBar += "" + ch; } progressBar += ']'; OHIF.log.info(displaySetInstanceUid + ": " + progressBar); } return _logProgress; }(); return StackLoadingListener; }(BaseLoadingListener); var StudyLoadingListener = /*#__PURE__*/ function () { function StudyLoadingListener() { this.listeners = {}; } var _proto4 = StudyLoadingListener.prototype; _proto4.addStack = function () { function addStack(stack, stackMetaData) { var displaySetInstanceUid = stack.displaySetInstanceUid; if (!this.listeners[displaySetInstanceUid]) { var listener = this._createListener(stack, stackMetaData); if (listener) { this.listeners[displaySetInstanceUid] = listener; } } } return addStack; }(); _proto4.addStudy = function () { function addStudy(study) { var _this3 = this; study.displaySets.forEach(function (displaySet) { var stack = OHIF.viewerbase.stackManager.findOrCreateStack(study, displaySet); _this3.addStack(stack, { isMultiFrame: displaySet.isMultiFrame }); }); } return addStudy; }(); _proto4.addStudies = function () { function addStudies(studies) { if (!studies || !studies.length) { return; } for (var i = 0; i < studies.length; i++) { this.addStudy(studies[i]); } } return addStudies; }(); _proto4.clear = function () { function clear() { var displaySetInstanceUids = Object.keys(this.listeners); var length = displaySetInstanceUids.length; for (var i = 0; i < length; i++) { var displaySetInstanceUid = displaySetInstanceUids[i]; var displaySet = this.listeners[displaySetInstanceUid]; displaySet.destroy(); } this.listeners = {}; } return clear; }(); _proto4._createListener = function () { function _createListener(stack, stackMetaData) { var schema = this._getSchema(stack); // A StackLoadingListener can be created if it's wadors or not a multiframe // wadouri instance (single file) that means "N" files will have to be // downloaded where "N" is the number of frames. DICOMFileLoadingListener // is created only if it's a single DICOM file and there's no way to know // how many frames has already been loaded (bytes/s instead of frames/s). if (schema === 'wadors' || !stackMetaData.isMultiFrame) { return new StackLoadingListener(stack); } else { return new DICOMFileLoadingListener(stack); } } return _createListener; }(); _proto4._getSchema = function () { function _getSchema(stack) { var imageId = stack.imageIds[0]; var colonIndex = imageId.indexOf(':'); return imageId.substring(0, colonIndex); } return _getSchema; }(); // Singleton StudyLoadingListener.getInstance = function () { function getInstance() { if (!StudyLoadingListener._instance) { StudyLoadingListener._instance = new StudyLoadingListener(); } return StudyLoadingListener._instance; } return getInstance; }(); return StudyLoadingListener; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"StudyMetadataSource.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/StudyMetadataSource.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ StudyMetadataSource: function () { return StudyMetadataSource; } }); var OHIFError; module.watch(require("./OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 0); var StudyMetadataSource = /*#__PURE__*/ function () { function StudyMetadataSource() {} var _proto = StudyMetadataSource.prototype; /** * Get study metadata for a study with given study InstanceUID. * @param {String} studyInstanceUID Study InstanceUID. */ _proto.getByInstanceUID = function () { function getByInstanceUID(studyInstanceUID) { /** * Please override this method on a specialized class. */ throw new OHIFError('StudyMetadataSource::getByInstanceUID is not overriden. Please, override it in a specialized class. See OHIFStudyMetadataSource for example'); } return getByInstanceUID; }(); /** * Load study info and study metadata for a given study into the viewer. * @param {StudySummary|StudyMetadata} study of StudySummary or StudyMetadata object. */ _proto.loadStudy = function () { function loadStudy(study) { /** * Please override this method on a specialized class. */ throw new OHIFError('StudyMetadataSource::loadStudy is not overriden. Please, override it in a specialized class. See OHIFStudyMetadataSource for example'); } return loadStudy; }(); return StudyMetadataSource; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"StudyPrefetcher.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/StudyPrefetcher.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ StudyPrefetcher: function () { return StudyPrefetcher; } }); var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 1); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 2); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 3); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 4); var OHIFError; module.watch(require("./OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 5); var StackManager; module.watch(require("../StackManager.js"), { StackManager: function (v) { StackManager = v; } }, 6); var getImageId; module.watch(require("../getImageId.js"), { getImageId: function (v) { getImageId = v; } }, 7); var StudyPrefetcher = /*#__PURE__*/ function () { function StudyPrefetcher(studies) { this.studies = studies || []; this.prefetchDisplaySetsTimeout = 300; this.lastActiveViewportElement = null; this.cacheFullHandlerBound = _.bind(this.cacheFullHandler, this); cornerstone.events.addEventListener('cornerstoneimagecachefull.StudyPrefetcher', this.cacheFullHandlerBound); } var _proto = StudyPrefetcher.prototype; _proto.destroy = function () { function destroy() { this.stopPrefetching(); cornerstone.events.removeEventListener('cornerstoneimagecachefull.StudyPrefetcher', this.cacheFullHandlerBound); } return destroy; }(); StudyPrefetcher.getInstance = function () { function getInstance() { if (!StudyPrefetcher.instance) { StudyPrefetcher.instance = new StudyPrefetcher(); } return StudyPrefetcher.instance; } return getInstance; }(); _proto.setStudies = function () { function setStudies(studies) { this.stopPrefetching(); this.studies = studies; } return setStudies; }(); _proto.prefetch = function () { function prefetch() { if (!this.studies || !this.studies.length) { return; } this.stopPrefetching(); this.prefetchActiveViewport(); this.prefetchDisplaySets(); } return prefetch; }(); _proto.stopPrefetching = function () { function stopPrefetching() { this.disableViewportPrefetch(); cornerstoneTools.requestPoolManager.clearRequestStack('prefetch'); } return stopPrefetching; }(); _proto.prefetchActiveViewport = function () { function prefetchActiveViewport() { var activeViewportElement = OHIF.viewerbase.viewportUtils.getActiveViewportElement(); this.enablePrefetchOnElement(activeViewportElement); this.attachActiveViewportListeners(activeViewportElement); } return prefetchActiveViewport; }(); _proto.disableViewportPrefetch = function () { function disableViewportPrefetch() { $('.imageViewerViewport').each(function () { if (!$(this).find('canvas').length) { return; } cornerstoneTools.stackPrefetch.disable(this); }); } return disableViewportPrefetch; }(); _proto.hasStack = function () { function hasStack(element) { var stack = cornerstoneTools.getToolState(element, 'stack'); return stack && stack.data.length && stack.data[0].imageIds.length > 1; } return hasStack; }(); /** * This function enables stack prefetching for a specified element (viewport) * It first disables any prefetching currently occurring on any other viewports. * * @param element {node} DOM Node representing the viewport element */ _proto.enablePrefetchOnElement = function () { function enablePrefetchOnElement(element) { if (!$(element).find('canvas').length) { return; } // Make sure there is a stack to fetch if (this.hasStack(element)) { // Check if this is a clip or not var activeViewportIndex = Session.get('activeViewport'); var displaySetInstanceUid = OHIF.viewer.data.loadedSeriesData[activeViewportIndex].displaySetInstanceUid; var stack = StackManager.findStack(displaySetInstanceUid); if (!stack) { throw new OHIFError("Requested stack " + displaySetInstanceUid + " was not created"); } cornerstoneTools.stackPrefetch.enable(element); } } return enablePrefetchOnElement; }(); _proto.attachActiveViewportListeners = function () { function attachActiveViewportListeners(activeViewportElement) { function newImageHandler() { // It needs to be called asynchronously because cornerstone does it at the same way. // All instance urls to be prefetched will be removed again if we add them before // Cornerstone callback (see stackPrefetch.onImageUpdated). StudyPrefetcher.prefetchDisplaySetsAsync(); } if (this.lastActiveViewportElement) { this.lastActiveViewportElement.removeEventListener('cornerstonenewimage.StudyPrefetcher', newImageHandler); } activeViewportElement.removeEventListener('cornerstonenewimage.StudyPrefetcher', newImageHandler); // Cornerstone will not attach an event listener if the element doesn't have a stack if (this.hasStack(activeViewportElement)) { activeViewportElement.addEventListener('cornerstonenewimage.StudyPrefetcher', newImageHandler); } this.lastActiveViewportElement = activeViewportElement; } return attachActiveViewportListeners; }(); _proto.prefetchDisplaySetsAsync = function () { function prefetchDisplaySetsAsync(timeout) { var _this = this; timeout = timeout || this.prefetchDisplaySetsTimeout; clearTimeout(this.prefetchDisplaySetsHandler); this.prefetchDisplaySetsHandler = setTimeout(function () { _this.prefetchDisplaySets(); }, timeout); } return prefetchDisplaySetsAsync; }(); _proto.prefetchDisplaySets = function () { function prefetchDisplaySets() { var config; if (Meteor.settings && Meteor.settings.public && Meteor.settings.prefetch) { config = Meteor.settings.public.prefetch; } else { config = { order: 'closest', displaySetCount: 1 }; } var displaySetsToPrefetch = this.getDisplaySetsToPrefetch(config); var imageIds = this.getImageIdsFromDisplaySets(displaySetsToPrefetch); this.prefetchImageIds(imageIds); } return prefetchDisplaySets; }(); _proto.prefetchImageIds = function () { function prefetchImageIds(imageIds) { var nonCachedImageIds = this.filterCachedImageIds(imageIds); var requestPoolManager = cornerstoneTools.requestPoolManager; var requestType = 'prefetch'; var preventCache = false; var noop = function () {}; nonCachedImageIds.forEach(function (imageId) { requestPoolManager.addRequest({}, imageId, requestType, preventCache, noop, noop); }); requestPoolManager.startGrabbing(); } return prefetchImageIds; }(); _proto.getActiveViewportImage = function () { function getActiveViewportImage() { var element = OHIF.viewerbase.viewportUtils.getActiveViewportElement(); if (!element) { return; } var enabledElement = cornerstone.getEnabledElement(element); var image = enabledElement.image; return image; } return getActiveViewportImage; }(); _proto.getStudy = function () { function getStudy(image) { var studyMetadata = cornerstone.metaData.get('study', image.imageId); return OHIF.viewer.Studies.find(function (study) { return study.studyInstanceUid === studyMetadata.studyInstanceUid; }); } return getStudy; }(); _proto.getSeries = function () { function getSeries(study, image) { var seriesMetadata = cornerstone.metaData.get('series', image.imageId); var studyMetadata = OHIF.viewerbase.getStudyMetadata(study); return studyMetadata.getSeriesByUID(seriesMetadata.seriesInstanceUid); } return getSeries; }(); _proto.getInstance = function () { function getInstance(series, image) { var instanceMetadata = cornerstone.metaData.get('instance', image.imageId); return series.getInstanceByUID(instanceMetadata.sopInstanceUid); } return getInstance; }(); _proto.getActiveDisplaySet = function () { function getActiveDisplaySet(displaySets, instance) { return _.find(displaySets, function (displaySet) { return _.some(displaySet.images, function (displaySetImage) { return displaySetImage.sopInstanceUid === instance.sopInstanceUid; }); }); } return getActiveDisplaySet; }(); _proto.getDisplaySetsToPrefetch = function () { function getDisplaySetsToPrefetch(config) { var image = this.getActiveViewportImage(); if (!image || !config || !config.displaySetCount) { return []; } var study = this.getStudy(image); var series = this.getSeries(study, image); var instance = this.getInstance(series, image); var displaySets = study.displaySets; var activeDisplaySet = this.getActiveDisplaySet(displaySets, instance); var prefetchMethodMap = { topdown: 'getFirstDisplaySets', downward: 'getNextDisplaySets', closest: 'getClosestDisplaySets' }; var prefetchOrder = config.order; var methodName = prefetchMethodMap[prefetchOrder]; var getDisplaySets = this[methodName]; if (!getDisplaySets) { if (prefetchOrder) { OHIF.log.warn("Invalid prefetch order configuration (" + prefetchOrder + ")"); } return []; } return getDisplaySets.call(this, displaySets, activeDisplaySet, config.displaySetCount); } return getDisplaySetsToPrefetch; }(); _proto.getFirstDisplaySets = function () { function getFirstDisplaySets(displaySets, activeDisplaySet, displaySetCount) { var length = displaySets.length; var selectedDisplaySets = []; for (var i = 0; i < length && displaySetCount; i++) { var displaySet = displaySets[i]; if (displaySet !== activeDisplaySet) { selectedDisplaySets.push(displaySet); displaySetCount--; } } return selectedDisplaySets; } return getFirstDisplaySets; }(); _proto.getNextDisplaySets = function () { function getNextDisplaySets(displaySets, activeDisplaySet, displaySetCount) { var activeDisplaySetIndex = displaySets.indexOf(activeDisplaySet); var begin = activeDisplaySetIndex + 1; var end = Math.min(begin + displaySetCount, displaySets.length); return displaySets.slice(begin, end); } return getNextDisplaySets; }(); _proto.getClosestDisplaySets = function () { function getClosestDisplaySets(displaySets, activeDisplaySet, displaySetCount) { var activeDisplaySetIndex = displaySets.indexOf(activeDisplaySet); var length = displaySets.length; var selectedDisplaySets = []; var left = activeDisplaySetIndex - 1; var right = activeDisplaySetIndex + 1; while ((left >= 0 || right < length) && displaySetCount) { if (left >= 0) { selectedDisplaySets.push(displaySets[left]); displaySetCount--; left--; } if (right < length && displaySetCount) { selectedDisplaySets.push(displaySets[right]); displaySetCount--; right++; } } return selectedDisplaySets; } return getClosestDisplaySets; }(); _proto.getImageIdsFromDisplaySets = function () { function getImageIdsFromDisplaySets(displaySets) { var _this2 = this; var imageIds = []; displaySets.forEach(function (displaySet) { imageIds = imageIds.concat(_this2.getImageIdsFromDisplaySet(displaySet)); }); return imageIds; } return getImageIdsFromDisplaySets; }(); _proto.getImageIdsFromDisplaySet = function () { function getImageIdsFromDisplaySet(displaySet) { var imageIds = []; displaySet.images.forEach(function (image) { var numFrames = image.numFrames; if (numFrames > 1) { for (var i = 0; i < numFrames; i++) { var imageId = getImageId(image, i); imageIds.push(imageId); } } else { var _imageId = getImageId(image); imageIds.push(_imageId); } }); return imageIds; } return getImageIdsFromDisplaySet; }(); _proto.filterCachedImageIds = function () { function filterCachedImageIds(imageIds) { var _this3 = this; return _.filter(imageIds, function (imageId) { return !_this3.isImageCached(imageId); }); } return filterCachedImageIds; }(); _proto.isImageCached = function () { function isImageCached(imageId) { var image = cornerstone.imageCache.imageCache[imageId]; return image && image.sizeInBytes; } return isImageCached; }(); _proto.cacheFullHandler = function () { function cacheFullHandler() { OHIF.log.warn('Cache full'); this.stopPrefetching(); } return cacheFullHandler; }(); return StudyPrefetcher; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"TypeSafeCollection.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/TypeSafeCollection.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); module.export({ TypeSafeCollection: function () { return TypeSafeCollection; } }); var Random; module.watch(require("meteor/random"), { Random: function (v) { Random = v; } }, 0); var ReactiveVar; module.watch(require("meteor/reactive-var"), { ReactiveVar: function (v) { ReactiveVar = v; } }, 1); /** * Constants */ var PROPERTY_SEPARATOR = '.'; var ORDER_ASC = 'asc'; var ORDER_DESC = 'desc'; var MIN_COUNT = 0x00000000; var MAX_COUNT = 0x7FFFFFFF; /** * Class Definition */ var TypeSafeCollection = /*#__PURE__*/ function () { function TypeSafeCollection() { this._operationCount = new ReactiveVar(MIN_COUNT); this._elementList = []; this._handlers = Object.create(null); } /** * Private Methods */ var _proto = TypeSafeCollection.prototype; _proto._invalidate = function () { function _invalidate() { var count = this._operationCount.get(); this._operationCount.set(count < MAX_COUNT ? count + 1 : MIN_COUNT); } return _invalidate; }(); _proto._elements = function () { function _elements(silent) { silent === true || this._operationCount.get(); return this._elementList; } return _elements; }(); _proto._elementWithPayload = function () { function _elementWithPayload(payload, silent) { return this._elements(silent).find(function (item) { return item.payload === payload; }); } return _elementWithPayload; }(); _proto._elementWithId = function () { function _elementWithId(id, silent) { return this._elements(silent).find(function (item) { return item.id === id; }); } return _elementWithId; }(); _proto._trigger = function () { function _trigger(event, data) { var handlers = this._handlers; if (event in handlers) { handlers = handlers[event]; if (!(handlers instanceof Array)) { return; } for (var i = 0, limit = handlers.length; i < limit; ++i) { var handler = handlers[i]; if (_isFunction(handler)) { handler.call(null, data); } } } } return _trigger; }(); /** * Public Methods */ _proto.onInsert = function () { function onInsert(callback) { if (_isFunction(callback)) { var handlers = this._handlers.insert; if (!(handlers instanceof Array)) { handlers = []; this._handlers.insert = handlers; } handlers.push(callback); } } return onInsert; }(); /** * Update the payload associated with the given ID to be the new supplied payload. * @param {string} id The ID of the entry that will be updated. * @param {any} payload The element that will replace the previous payload. * @returns {boolean} Returns true if the given ID is present in the collection, false otherwise. */ _proto.updateById = function () { function updateById(id, payload) { var result = false, found = this._elementWithPayload(payload, true); if (found) { // nothing to do since the element is already in the collection... if (found.id === id) { // set result to true since the ids match... result = true; this._invalidate(); } } else { found = this._elementWithId(id, true); if (found) { found.payload = payload; result = true; this._invalidate(); } } return result; } return updateById; }(); /** * Signal that the given element has been changed by notifying reactive data-source observers. * This method is basically a means to invalidate the inernal reactive data-source. * @param {any} payload The element that has been altered. * @returns {boolean} Returns true if the element is present in the collection, false otherwise. */ _proto.update = function () { function update(payload) { var result = false, found = this._elementWithPayload(payload, true); if (found) { // nothing to do since the element is already in the collection... result = true; this._invalidate(); } return result; } return update; }(); /** * Insert an element in the collection. On success, the element ID (a unique string) is returned. On failure, returns null. * A failure scenario only happens when the given payload is already present in the collection. Note that NO exceptions are thrown! * @param {any} payload The element to be stored. * @returns {string} The ID of the inserted element or null if the element already exists... */ _proto.insert = function () { function insert(payload) { var id = null, found = this._elementWithPayload(payload, true); if (!found) { id = Random.id(); this._elements(true).push({ id: id, payload: payload }); this._invalidate(); this._trigger('insert', { id: id, data: payload }); } return id; } return insert; }(); /** * Remove all elements from the collection. * @returns {void} No meaningful value is returned. */ _proto.removeAll = function () { function removeAll() { var all = this._elements(true), length = all.length; for (var i = length - 1; i >= 0; i--) { var item = all[i]; delete item.id; delete item.payload; all[i] = null; } all.splice(0, length); this._invalidate(); } return removeAll; }(); /** * Remove elements from the collection that match the criteria given in the property map. * @param {Object} propertyMap A property map that will be macthed against all collection elements. * @returns {Array} A list with all removed elements. */ _proto.remove = function () { function remove(propertyMap) { var found = this.findAllEntriesBy(propertyMap), foundCount = found.length, removed = []; if (foundCount > 0) { var _all = this._elements(true); for (var i = foundCount - 1; i >= 0; i--) { var item = found[i]; _all.splice(item[2], 1); removed.push(item[0]); } this._invalidate(); } return removed; } return remove; }(); /** * Provides the ID of the given element inside the collection. * @param {any} payload The element being searched for. * @returns {string} The ID of the given element or undefined if the element is not present. */ _proto.getElementId = function () { function getElementId(payload) { var found = this._elementWithPayload(payload); return found && found.id; } return getElementId; }(); /** * Provides the position of the given element in the internal list returning -1 if the element is not present. * @param {any} payload The element being searched for. * @returns {number} The position of the given element in the internal list. If the element is not present -1 is returned. */ _proto.findById = function () { function findById(id) { var found = this._elementWithId(id); return found && found.payload; } return findById; }(); /** * Provides the position of the given element in the internal list returning -1 if the element is not present. * @param {any} payload The element being searched for. * @returns {number} The position of the given element in the internal list. If the element is not present -1 is returned. */ _proto.indexOfElement = function () { function indexOfElement(payload) { return this._elements().indexOf(this._elementWithPayload(payload, true)); } return indexOfElement; }(); /** * Provides the position of the element associated with the given ID in the internal list returning -1 if the element is not present. * @param {string} id The index of the element. * @returns {number} The position of the element associated with the given ID in the internal list. If the element is not present -1 is returned. */ _proto.indexOfId = function () { function indexOfId(id) { return this._elements().indexOf(this._elementWithId(id, true)); } return indexOfId; }(); /** * Provides a list-like approach to the collection returning an element by index. * @param {number} index The index of the element. * @returns {any} If out of bounds, undefined is returned. Otherwise the element in the given position is returned. */ _proto.getElementByIndex = function () { function getElementByIndex(index) { var found = this._elements()[index >= 0 ? index : -1]; return found && found.payload; } return getElementByIndex; }(); /** * Find an element by a criteria defined by the given callback function. * Attention!!! The reactive source will not be notified if no valid callback is supplied... * @param {function} callback A callback function which will define the search criteria. The callback * function will be passed the collection element, its ID and its index in this very order. The callback * shall return true when its criterea has been fulfilled. * @returns {any} The matched element or undefined if not match was found. */ _proto.find = function () { function find(callback) { var _this = this; var found; if (_isFunction(callback)) { found = this._elements().find(function (item, index) { return callback.call(_this, item.payload, item.id, index); }); } return found && found.payload; } return find; }(); /** * Find the first element that strictly matches the specified property map. * @param {Object} propertyMap A property map that will be macthed against all collection elements. * @param {Object} options A set of options. Currently only "options.sort" option is supported. * @param {Object.SortingSpecifier} options.sort An optional sorting specifier. If a sorting specifier is supplied * but is not valid, an exception will be thrown. * @returns {Any} The matched element or undefined if not match was found. */ _proto.findBy = function () { function findBy(propertyMap, options) { var found; if (_isObject(options)) { // if the "options" argument is provided and is a valid object, // it must be applied to the dataset before search... var _all2 = this.all(options); if (_all2.length > 0) { if (_isObject(propertyMap)) { found = _all2.find(function (item) { return _compareToPropertyMapStrict(propertyMap, item); }); } else { found = _all2[0]; // simply extract the first element... } } } else if (_isObject(propertyMap)) { found = this._elements().find(function (item) { return _compareToPropertyMapStrict(propertyMap, item.payload); }); if (found) { found = found.payload; } } return found; } return findBy; }(); /** * Find all elements that strictly match the specified property map. * Attention!!! The reactive source will not be notified if no valid property map is supplied... * @param {Object} propertyMap A property map that will be macthed against all collection elements. * @returns {Array} An array of entries of all elements that match the given criteria. Each set in * in the array has the following format: [ elementData, elementId, elementIndex ]. */ _proto.findAllEntriesBy = function () { function findAllEntriesBy(propertyMap) { var found = []; if (_isObject(propertyMap)) { this._elements().forEach(function (item, index) { if (_compareToPropertyMapStrict(propertyMap, item.payload)) { // Match! Add it to the found list... found.push([item.payload, item.id, index]); } }); } return found; } return findAllEntriesBy; }(); /** * Find all elements that match a specified property map. * Attention!!! The reactive source will not be notified if no valid property map is supplied... * @param {Object} propertyMap A property map that will be macthed against all collection elements. * @param {Object} options A set of options. Currently only "options.sort" option is supported. * @param {Object.SortingSpecifier} options.sort An optional sorting specifier. If a sorting specifier is supplied * but is not valid, an exception will be thrown. * @returns {Array} An array with all elements that match the given criteria and sorted in the specified sorting order. */ _proto.findAllBy = function () { function findAllBy(propertyMap, options) { var found = this.findAllEntriesBy(propertyMap).map(function (item) { return item[0]; }); // Only payload is relevant... if (_isObject(options)) { if ('sort' in options) { _sortListBy(found, options.sort); } } return found; } return findAllBy; }(); /** * Executes the supplied callback function for each element of the collection. * Attention!!! The reactive source will not be notified if no valid property map is supplied... * @param {function} callback The callback function to be executed. The callback is passed the element, * its ID and its index in this very order. * @returns {void} Nothing is returned. */ _proto.forEach = function () { function forEach(callback) { var _this2 = this; if (_isFunction(callback)) { this._elements().forEach(function (item, index) { callback.call(_this2, item.payload, item.id, index); }); } } return forEach; }(); /** * Count the number of elements currently in the collection. * @returns {number} The current number of elements in the collection. */ _proto.count = function () { function count() { return this._elements().length; } return count; }(); /** * Returns a list with all elements of the collection optionally sorted by a sorting specifier criteria. * @param {Object} options A set of options. Currently only "options.sort" option is supported. * @param {Object.SortingSpecifier} options.sort An optional sorting specifier. If a sorting specifier is supplied * but is not valid, an exception will be thrown. * @returns {Array} An array with all elements stored in the collection. */ _proto.all = function () { function all(options) { var list = this._elements().map(function (item) { return item.payload; }); if (_isObject(options)) { if ('sort' in options) { _sortListBy(list, options.sort); } } return list; } return all; }(); return TypeSafeCollection; }(); /** * Utility Functions */ /** * Test if supplied argument is a valid object for current class purposes. * Atention! The underscore version of this function should not be used for performance reasons. */ function _isObject(subject) { return subject instanceof Object || (0, _typeof2.default)(subject) === 'object' && subject !== null; } /** * Test if supplied argument is a valid string for current class purposes. * Atention! The underscore version of this function should not be used for performance reasons. */ function _isString(subject) { return typeof subject === 'string'; } /** * Test if supplied argument is a valid function for current class purposes. * Atention! The underscore version of this function should not be used for performance reasons. */ function _isFunction(subject) { return typeof subject === 'function'; } /** * Shortcut for Object's prototype "hasOwnProperty" method. */ var _hasOwnProperty = Object.prototype.hasOwnProperty; /** * Retrieve an object's property value by name. Composite property names (e.g., 'address.country.name') are accepted. * @param {Object} targetObject The object we want read the property from... * @param {String} propertyName The property to be read (e.g., 'address.street.name' or 'address.street.number' * to read object.address.street.name or object.address.street.number, respectively); * @returns {Any} Returns whatever the property holds or undefined if the property cannot be read or reached. */ function _getPropertyValue(targetObject, propertyName) { var propertyValue; // undefined (the default return value) if (_isObject(targetObject) && _isString(propertyName)) { var fragments = propertyName.split(PROPERTY_SEPARATOR); var fragmentCount = fragments.length; if (fragmentCount > 0) { var firstFragment = fragments[0]; var remainingFragments = fragmentCount > 1 ? fragments.slice(1).join(PROPERTY_SEPARATOR) : null; propertyValue = targetObject[firstFragment]; if (remainingFragments !== null) { propertyValue = _getPropertyValue(propertyValue, remainingFragments); } } } return propertyValue; } /** * Compare a property map with a target object using strict comparison. * @param {Object} propertyMap The property map whose properties will be used for comparison. Composite * property names (e.g., 'address.country.name') will be tested against the "resolved" properties from the target object. * @param {Object} targetObject The target object whose properties will be tested. * @returns {boolean} Returns true if the properties match, false otherwise. */ function _compareToPropertyMapStrict(propertyMap, targetObject) { var result = false; // "for in" loops do not thown exceptions for invalid data types... for (var propertyName in meteorBabelHelpers.sanitizeForInObject(propertyMap)) { if (_hasOwnProperty.call(propertyMap, propertyName)) { if (propertyMap[propertyName] !== _getPropertyValue(targetObject, propertyName)) { result = false; break; } else if (result !== true) { result = true; } } } return result; } /** * Checks if a sorting specifier is valid. * A valid sorting specifier consists of an array of arrays being each subarray a pair * in the format ["property name", "sorting order"]. * The following exemple can be used to sort studies by "date"" and use "time" to break ties in descending order. * [ [ 'study.date', 'desc' ], [ 'study.time', 'desc' ] ] * @param {Array} specifiers The sorting specifier to be tested. * @returns {boolean} Returns true if the specifiers are valid, false otherwise. */ function _isValidSortingSpecifier(specifiers) { var result = true; if (specifiers instanceof Array && specifiers.length > 0) { for (var i = specifiers.length - 1; i >= 0; i--) { var item = specifiers[i]; if (item instanceof Array) { var property = item[0]; var order = item[1]; if (_isString(property) && (order === ORDER_ASC || order === ORDER_DESC)) { continue; } } result = false; break; } } return result; } /** * Sorts an array based on sorting specifier options. * @param {Array} list The that needs to be sorted. * @param {Array} specifiers An array of specifiers. Please read isValidSortingSpecifier method definition for further details. * @returns {void} No value is returned. The array is sorted in place. */ function _sortListBy(list, specifiers) { if (list instanceof Array && _isValidSortingSpecifier(specifiers)) { var specifierCount = specifiers.length; list.sort(function () { function _sortListByCallback(a, b) { // callback name for stack traces... var index = 0; while (index < specifierCount) { var specifier = specifiers[index]; var property = specifier[0]; var order = specifier[1] === ORDER_DESC ? -1 : 1; var aValue = _getPropertyValue(a, property); var bValue = _getPropertyValue(b, property); // @TODO: should we check for the types being compared, like: // ~~ if (typeof aValue !== typeof bValue) continue; // Not sure because dates, for example, can be correctly compared to numbers... if (aValue < bValue) { return order * -1; } if (aValue > bValue) { return order * 1; } if (++index >= specifierCount) { return 0; } } } return _sortListByCallback; }()); } else { throw new Error('Invalid Arguments'); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"metadata":{"InstanceMetadata.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/metadata/InstanceMetadata.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); module.export({ InstanceMetadata: function () { return InstanceMetadata; } }); var Metadata; module.watch(require("./Metadata"), { Metadata: function (v) { Metadata = v; } }, 0); var OHIFError; module.watch(require("../OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 1); /** * ATTENTION! This class should never depend on StudyMetadata or SeriesMetadata classes as this could * possibly cause circular dependency issues. */ var UNDEFINED = 'undefined'; var NUMBER = 'number'; var STRING = 'string'; var STUDY_INSTANCE_UID = 'x0020000d'; var SERIES_INSTANCE_UID = 'x0020000e'; var InstanceMetadata = /*#__PURE__*/ function (_Metadata) { (0, _inheritsLoose2.default)(InstanceMetadata, _Metadata); function InstanceMetadata(data, uid) { var _this; _this = _Metadata.call(this, data, uid) || this; // Initialize Private Properties Object.defineProperties((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), { _sopInstanceUID: { configurable: true, // configurable so that it can be redefined in sub-classes... enumerable: false, writable: true, value: null }, _imageId: { configurable: true, // configurable so that it can be redefined in sub-classes... enumerable: false, writable: true, value: null } }); // Initialize Public Properties _this._definePublicProperties(); return _this; } /** * Private Methods */ /** * Define Public Properties * This method should only be called during initialization (inside the class constructor) */ var _proto = InstanceMetadata.prototype; _proto._definePublicProperties = function () { function _definePublicProperties() { /** * Property: this.sopInstanceUID * Same as this.getSOPInstanceUID() * It's specially useful in contexts where a method call is not suitable like in search criteria. For example: * sopInstanceCollection.findBy({ * sopInstanceUID: '1.2.3.4.5.6.77777.8888888.99999999999.0' * }); */ Object.defineProperty(this, 'sopInstanceUID', { configurable: false, enumerable: false, get: function () { return this.getSOPInstanceUID(); } }); } return _definePublicProperties; }(); /** * Public Methods */ /** * Returns the StudyInstanceUID of the current instance. This method is basically a shorthand the full "getTagValue" method call. */ _proto.getStudyInstanceUID = function () { function getStudyInstanceUID() { return this.getTagValue(STUDY_INSTANCE_UID, null); } return getStudyInstanceUID; }(); /** * Returns the SeriesInstanceUID of the current instance. This method is basically a shorthand the full "getTagValue" method call. */ _proto.getSeriesInstanceUID = function () { function getSeriesInstanceUID() { return this.getTagValue(SERIES_INSTANCE_UID, null); } return getSeriesInstanceUID; }(); /** * Returns the SOPInstanceUID of the current instance. */ _proto.getSOPInstanceUID = function () { function getSOPInstanceUID() { return this._sopInstanceUID; } return getSOPInstanceUID; }(); // @TODO: Improve this... (E.g.: blob data) _proto.getStringValue = function () { function getStringValue(tagOrProperty, index, defaultValue) { var value = this.getTagValue(tagOrProperty, defaultValue); if ((0, _typeof2.default)(value) !== STRING && (0, _typeof2.default)(value) !== UNDEFINED) { value = value.toString(); } return InstanceMetadata.getIndexedValue(value, index, defaultValue); } return getStringValue; }(); // @TODO: Improve this... (E.g.: blob data) _proto.getFloatValue = function () { function getFloatValue(tagOrProperty, index, defaultValue) { var value = this.getTagValue(tagOrProperty, defaultValue); value = InstanceMetadata.getIndexedValue(value, index, defaultValue); if (value instanceof Array) { value.forEach(function (val, idx) { value[idx] = parseFloat(val); }); return value; } return (0, _typeof2.default)(value) === STRING ? parseFloat(value) : value; } return getFloatValue; }(); // @TODO: Improve this... (E.g.: blob data) _proto.getIntValue = function () { function getIntValue(tagOrProperty, index, defaultValue) { var value = this.getTagValue(tagOrProperty, defaultValue); value = InstanceMetadata.getIndexedValue(value, index, defaultValue); if (value instanceof Array) { value.forEach(function (val, idx) { value[idx] = parseFloat(val); }); return value; } return (0, _typeof2.default)(value) === STRING ? parseInt(value) : value; } return getIntValue; }(); /** * @deprecated Please use getTagValue instead. */ _proto.getRawValue = function () { function getRawValue(tagOrProperty, defaultValue) { return this.getTagValue(tagOrProperty, defaultValue); } return getRawValue; }(); /** * This function should be overriden by specialized classes in order to allow client libraries or viewers to take advantage of the Study Metadata API. */ _proto.getTagValue = function () { function getTagValue(tagOrProperty, defaultValue) { /** * Please override this method on a specialized class. */ throw new OHIFError('InstanceMetadata::getTagValue is not overriden. Please, override it in a specialized class. See OHIFInstanceMetadata for example'); } return getTagValue; }(); /** * Compares the current instance with another one. * @param {InstanceMetadata} instance An instance of the InstanceMetadata class. * @returns {boolean} Returns true if both instances refer to the same instance. */ _proto.equals = function () { function equals(instance) { var self = this; return instance === self || instance instanceof InstanceMetadata && instance.getSOPInstanceUID() === self.getSOPInstanceUID(); } return equals; }(); /** * Check if the tagOrProperty exists * @param {String} tagOrProperty tag or property be checked * @return {Boolean} True if the tag or property exists or false if doesn't */ _proto.tagExists = function () { function tagExists(tagOrProperty) { /** * Please override this method */ throw new OHIFError('InstanceMetadata::tagExists is not overriden. Please, override it in a specialized class. See OHIFInstanceMetadata for example'); } return tagExists; }(); /** * Get custom image id of a sop instance * @return {Any} sop instance image id */ _proto.getImageId = function () { function getImageId(frame) { /** * Please override this method */ throw new OHIFError('InstanceMetadata::getImageId is not overriden. Please, override it in a specialized class. See OHIFInstanceMetadata for example'); } return getImageId; }(); /** * Static Methods */ /** * Get an value based that can be index based. This function is called by all getters. See above functions. * - If value is a String and has indexes: * - If undefined index: returns an array of the split values. * - If defined index: * - If invalid: returns defaultValue * - If valid: returns the indexed value * - If value is not a String, returns default value. */ InstanceMetadata.getIndexedValue = function () { function getIndexedValue(value, index, defaultValue) { var result = defaultValue; if ((0, _typeof2.default)(value) === STRING) { var hasIndexValues = value.indexOf('\\') !== -1; result = value; if (hasIndexValues) { var splitValues = value.split('\\'); if (Metadata.isValidIndex(index)) { var indexedValue = splitValues[index]; result = (0, _typeof2.default)(indexedValue) !== STRING ? defaultValue : indexedValue; } else { result = splitValues; } } } return result; } return getIndexedValue; }(); return InstanceMetadata; }(Metadata); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"Metadata.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/metadata/Metadata.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); module.export({ Metadata: function () { return Metadata; } }); /** * Constants */ var STRING = 'string'; var NUMBER = 'number'; var FUNCTION = 'function'; var OBJECT = 'object'; /** * Class Definition */ var Metadata = /*#__PURE__*/ function () { /** * Constructor and Instance Methods */ function Metadata(data, uid) { // Define the main "_data" private property as an immutable property. // IMPORTANT: This property can only be set during instance construction. Object.defineProperty(this, '_data', { configurable: false, enumerable: false, writable: false, value: data }); // Define the main "_uid" private property as an immutable property. // IMPORTANT: This property can only be set during instance construction. Object.defineProperty(this, '_uid', { configurable: false, enumerable: false, writable: false, value: uid }); // Define "_custom" properties as an immutable property. // IMPORTANT: This property can only be set during instance construction. Object.defineProperty(this, '_custom', { configurable: false, enumerable: false, writable: false, value: Object.create(null) }); } var _proto = Metadata.prototype; _proto.getData = function () { function getData() { return this._data; } return getData; }(); _proto.getDataProperty = function () { function getDataProperty(propertyName) { var propertyValue; var _data = this._data; if (_data instanceof Object || (0, _typeof2.default)(_data) === OBJECT && _data !== null) { propertyValue = _data[propertyName]; } return propertyValue; } return getDataProperty; }(); /** * Get unique object ID */ _proto.getObjectID = function () { function getObjectID() { return this._uid; } return getObjectID; }(); /** * Set custom attribute value * @param {String} attribute Custom attribute name * @param {Any} value Custom attribute value */ _proto.setCustomAttribute = function () { function setCustomAttribute(attribute, value) { this._custom[attribute] = value; } return setCustomAttribute; }(); /** * Get custom attribute value * @param {String} attribute Custom attribute name * @return {Any} Custom attribute value */ _proto.getCustomAttribute = function () { function getCustomAttribute(attribute) { return this._custom[attribute]; } return getCustomAttribute; }(); /** * Check if a custom attribute exists * @param {String} attribute Custom attribute name * @return {Boolean} True if custom attribute exists or false if not */ _proto.customAttributeExists = function () { function customAttributeExists(attribute) { return attribute in this._custom; } return customAttributeExists; }(); /** * Set custom attributes in batch mode. * @param {Object} attributeMap An object whose own properties will be used as custom attributes. */ _proto.setCustomAttributes = function () { function setCustomAttributes(attributeMap) { var _hasOwn = Object.prototype.hasOwnProperty; var _custom = this._custom; for (var attribute in meteorBabelHelpers.sanitizeForInObject(attributeMap)) { if (_hasOwn.call(attributeMap, attribute)) { _custom[attribute] = attributeMap[attribute]; } } } return setCustomAttributes; }(); /** * Static Methods */ Metadata.isValidUID = function () { function isValidUID(uid) { return (0, _typeof2.default)(uid) === STRING && uid.length > 0; } return isValidUID; }(); Metadata.isValidIndex = function () { function isValidIndex(index) { return (0, _typeof2.default)(index) === NUMBER && index >= 0 && (index | 0) === index; } return isValidIndex; }(); Metadata.isValidCallback = function () { function isValidCallback(callback) { return (0, _typeof2.default)(callback) === FUNCTION; } return isValidCallback; }(); return Metadata; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"SeriesMetadata.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/metadata/SeriesMetadata.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); module.export({ SeriesMetadata: function () { return SeriesMetadata; } }); var Metadata; module.watch(require("./Metadata"), { Metadata: function (v) { Metadata = v; } }, 0); var InstanceMetadata; module.watch(require("./InstanceMetadata"), { InstanceMetadata: function (v) { InstanceMetadata = v; } }, 1); var SeriesMetadata = /*#__PURE__*/ function (_Metadata) { (0, _inheritsLoose2.default)(SeriesMetadata, _Metadata); function SeriesMetadata(data, uid) { var _this; _this = _Metadata.call(this, data, uid) || this; // Initialize Private Properties Object.defineProperties((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), { _seriesInstanceUID: { configurable: true, // configurable so that it can be redefined in sub-classes... enumerable: false, writable: true, value: null }, _instances: { configurable: false, enumerable: false, writable: false, value: [] }, _firstInstance: { configurable: false, enumerable: false, writable: true, value: null } }); // Initialize Public Properties _this._definePublicProperties(); return _this; } /** * Private Methods */ /** * Define Public Properties * This method should only be called during initialization (inside the class constructor) */ var _proto = SeriesMetadata.prototype; _proto._definePublicProperties = function () { function _definePublicProperties() { /** * Property: this.seriesInstanceUID * Same as this.getSeriesInstanceUID() * It's specially useful in contexts where a method call is not suitable like in search criteria. For example: * seriesCollection.findBy({ * seriesInstanceUID: '1.2.3.4.5.6.77777.8888888.99999999999.0' * }); */ Object.defineProperty(this, 'seriesInstanceUID', { configurable: false, enumerable: false, get: function () { return this.getSeriesInstanceUID(); } }); } return _definePublicProperties; }(); /** * Public Methods */ /** * Returns the SeriesInstanceUID of the current series. */ _proto.getSeriesInstanceUID = function () { function getSeriesInstanceUID() { return this._seriesInstanceUID; } return getSeriesInstanceUID; }(); /** * Append an instance to the current series. * @param {InstanceMetadata} instance The instance to be added to the current series. * @returns {boolean} Returns true on success, false otherwise. */ _proto.addInstance = function () { function addInstance(instance) { var result = false; if (instance instanceof InstanceMetadata && this.getInstanceByUID(instance.getSOPInstanceUID()) === void 0) { this._instances.push(instance); result = true; } return result; } return addInstance; }(); /** * Get the first instance of the current series retaining a consistent result across multiple calls. * @return {InstanceMetadata} An instance of the InstanceMetadata class or null if it does not exist. */ _proto.getFirstInstance = function () { function getFirstInstance() { var instance = this._firstInstance; if (!(instance instanceof InstanceMetadata)) { instance = null; var found = this.getInstanceByIndex(0); if (found instanceof InstanceMetadata) { this._firstInstance = found; instance = found; } } return instance; } return getFirstInstance; }(); /** * Find an instance by index. * @param {number} index An integer representing a list index. * @returns {InstanceMetadata} Returns a InstanceMetadata instance when found or undefined otherwise. */ _proto.getInstanceByIndex = function () { function getInstanceByIndex(index) { var found; // undefined by default... if (Metadata.isValidIndex(index)) { found = this._instances[index]; } return found; } return getInstanceByIndex; }(); /** * Find an instance by SOPInstanceUID. * @param {string} uid An UID string. * @returns {InstanceMetadata} Returns a InstanceMetadata instance when found or undefined otherwise. */ _proto.getInstanceByUID = function () { function getInstanceByUID(uid) { var found; // undefined by default... if (Metadata.isValidUID(uid)) { found = this._instances.find(function (instance) { return instance.getSOPInstanceUID() === uid; }); } return found; } return getInstanceByUID; }(); /** * Retrieve the number of instances within the current series. * @returns {number} The number of instances in the current series. */ _proto.getInstanceCount = function () { function getInstanceCount() { return this._instances.length; } return getInstanceCount; }(); /** * Invokes the supplied callback for each instance in the current series passing * two arguments: instance (an InstanceMetadata instance) and index (the integer * index of the instance within the current series) * @param {function} callback The callback function which will be invoked for each instance in the series. * @returns {undefined} Nothing is returned. */ _proto.forEachInstance = function () { function forEachInstance(callback) { if (Metadata.isValidCallback(callback)) { this._instances.forEach(function (instance, index) { callback.call(null, instance, index); }); } } return forEachInstance; }(); /** * Find the index of an instance inside the series. * @param {InstanceMetadata} instance An instance of the SeriesMetadata class. * @returns {number} The index of the instance inside the series or -1 if not found. */ _proto.indexOfInstance = function () { function indexOfInstance(instance) { return this._instances.indexOf(instance); } return indexOfInstance; }(); /** * Search the associated instances using the supplied callback as criteria. The callback is passed * two arguments: instance (a InstanceMetadata instance) and index (the integer * index of the instance within its series) * @param {function} callback The callback function which will be invoked for each instance. * @returns {InstanceMetadata|undefined} If an instance is found based on callback criteria it * returns a InstanceMetadata. "undefined" is returned otherwise */ _proto.findInstance = function () { function findInstance(callback) { if (Metadata.isValidCallback(callback)) { return this._instances.find(function (instance, index) { return callback.call(null, instance, index); }); } } return findInstance; }(); /** * Compares the current series with another one. * @param {SeriesMetadata} series An instance of the SeriesMetadata class. * @returns {boolean} Returns true if both instances refer to the same series. */ _proto.equals = function () { function equals(series) { var self = this; return series === self || series instanceof SeriesMetadata && series.getSeriesInstanceUID() === self.getSeriesInstanceUID(); } return equals; }(); return SeriesMetadata; }(Metadata); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"StudyMetadata.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/metadata/StudyMetadata.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized")); module.export({ StudyMetadata: function () { return StudyMetadata; } }); var Metadata; module.watch(require("./Metadata"), { Metadata: function (v) { Metadata = v; } }, 0); var SeriesMetadata; module.watch(require("./SeriesMetadata"), { SeriesMetadata: function (v) { SeriesMetadata = v; } }, 1); var InstanceMetadata; module.watch(require("./InstanceMetadata"), { InstanceMetadata: function (v) { InstanceMetadata = v; } }, 2); var ImageSet; module.watch(require("../ImageSet"), { ImageSet: function (v) { ImageSet = v; } }, 3); var OHIFError; module.watch(require("../OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 4); var StudyMetadata = /*#__PURE__*/ function (_Metadata) { (0, _inheritsLoose2.default)(StudyMetadata, _Metadata); function StudyMetadata(data, uid) { var _this; _this = _Metadata.call(this, data, uid) || this; // Initialize Private Properties Object.defineProperties((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), { _studyInstanceUID: { configurable: true, // configurable so that it can be redefined in sub-classes... enumerable: false, writable: true, value: null }, _series: { configurable: false, enumerable: false, writable: false, value: [] }, _displaySets: { configurable: false, enumerable: false, writable: false, value: [] }, _firstSeries: { configurable: false, enumerable: false, writable: true, value: null }, _firstInstance: { configurable: false, enumerable: false, writable: true, value: null } }); // Initialize Public Properties _this._definePublicProperties(); return _this; } /** * Private Methods */ /** * Define Public Properties * This method should only be called during initialization (inside the class constructor) */ var _proto = StudyMetadata.prototype; _proto._definePublicProperties = function () { function _definePublicProperties() { /** * Property: this.studyInstanceUID * Same as this.getStudyInstanceUID() * It's specially useful in contexts where a method call is not suitable like in search criteria. For example: * studyCollection.findBy({ * studyInstanceUID: '1.2.3.4.5.6.77777.8888888.99999999999.0' * }); */ Object.defineProperty(this, 'studyInstanceUID', { configurable: false, enumerable: false, get: function () { return this.getStudyInstanceUID(); } }); } return _definePublicProperties; }(); /** * Public Methods */ /** * Getter for displaySets * @return {Array} Array of display set object */ _proto.getDisplaySets = function () { function getDisplaySets() { return this._displaySets.slice(); } return getDisplaySets; }(); /** * Set display sets * @param {Array} displaySets Array of display sets (ImageSet[]) */ _proto.setDisplaySets = function () { function setDisplaySets(displaySets) { var _this2 = this; displaySets.forEach(function (displaySet) { return _this2.addDisplaySet(displaySet); }); } return setDisplaySets; }(); /** * Add a single display set to the list * @param {Object} displaySet Display set object * @returns {boolean} True on success, false on failure. */ _proto.addDisplaySet = function () { function addDisplaySet(displaySet) { if (displaySet instanceof ImageSet) { this._displaySets.push(displaySet); return true; } return false; } return addDisplaySet; }(); /** * Invokes the supplied callback for each display set in the current study passing * two arguments: display set (a ImageSet instance) and index (the integer * index of the display set within the current study) * @param {function} callback The callback function which will be invoked for each display set instance. * @returns {undefined} Nothing is returned. */ _proto.forEachDisplaySet = function () { function forEachDisplaySet(callback) { if (Metadata.isValidCallback(callback)) { this._displaySets.forEach(function (displaySet, index) { callback.call(null, displaySet, index); }); } } return forEachDisplaySet; }(); /** * Search the associated display sets using the supplied callback as criteria. The callback is passed * two arguments: display set (a ImageSet instance) and index (the integer * index of the display set within the current study) * @param {function} callback The callback function which will be invoked for each display set instance. * @returns {undefined} Nothing is returned. */ _proto.findDisplaySet = function () { function findDisplaySet(callback) { if (Metadata.isValidCallback(callback)) { return this._displaySets.find(function (displaySet, index) { return callback.call(null, displaySet, index); }); } } return findDisplaySet; }(); /** * Retrieve the number of display sets within the current study. * @returns {number} The number of display sets in the current study. */ _proto.getDisplaySetCount = function () { function getDisplaySetCount() { return this._displaySets.length; } return getDisplaySetCount; }(); /** * Returns the StudyInstanceUID of the current study. */ _proto.getStudyInstanceUID = function () { function getStudyInstanceUID() { return this._studyInstanceUID; } return getStudyInstanceUID; }(); /** * Getter for series * @return {Array} Array of SeriesMetadata object */ _proto.getSeries = function () { function getSeries() { return this._series.slice(); } return getSeries; }(); /** * Append a series to the current study. * @param {SeriesMetadata} series The series to be added to the current study. * @returns {boolean} Returns true on success, false otherwise. */ _proto.addSeries = function () { function addSeries(series) { var result = false; if (series instanceof SeriesMetadata && this.getSeriesByUID(series.getSeriesInstanceUID()) === void 0) { this._series.push(series); result = true; } return result; } return addSeries; }(); /** * Find a series by index. * @param {number} index An integer representing a list index. * @returns {SeriesMetadata} Returns a SeriesMetadata instance when found or undefined otherwise. */ _proto.getSeriesByIndex = function () { function getSeriesByIndex(index) { var found; // undefined by default... if (Metadata.isValidIndex(index)) { found = this._series[index]; } return found; } return getSeriesByIndex; }(); /** * Find a series by SeriesInstanceUID. * @param {string} uid An UID string. * @returns {SeriesMetadata} Returns a SeriesMetadata instance when found or undefined otherwise. */ _proto.getSeriesByUID = function () { function getSeriesByUID(uid) { var found; // undefined by default... if (Metadata.isValidUID(uid)) { found = this._series.find(function (series) { return series.getSeriesInstanceUID() === uid; }); } return found; } return getSeriesByUID; }(); /** * Retrieve the number of series within the current study. * @returns {number} The number of series in the current study. */ _proto.getSeriesCount = function () { function getSeriesCount() { return this._series.length; } return getSeriesCount; }(); /** * Retrieve the number of instances within the current study. * @returns {number} The number of instances in the current study. */ _proto.getInstanceCount = function () { function getInstanceCount() { return this._series.reduce(function (sum, series) { return sum + series.getInstanceCount(); }, 0); } return getInstanceCount; }(); /** * Invokes the supplied callback for each series in the current study passing * two arguments: series (a SeriesMetadata instance) and index (the integer * index of the series within the current study) * @param {function} callback The callback function which will be invoked for each series instance. * @returns {undefined} Nothing is returned. */ _proto.forEachSeries = function () { function forEachSeries(callback) { if (Metadata.isValidCallback(callback)) { this._series.forEach(function (series, index) { callback.call(null, series, index); }); } } return forEachSeries; }(); /** * Find the index of a series inside the study. * @param {SeriesMetadata} series An instance of the SeriesMetadata class. * @returns {number} The index of the series inside the study or -1 if not found. */ _proto.indexOfSeries = function () { function indexOfSeries(series) { return this._series.indexOf(series); } return indexOfSeries; }(); /** * It sorts the series based on display sets order. Each series must be an instance * of SeriesMetadata and each display sets must be an instance of ImageSet. * Useful example of usage: * Study data provided by backend does not sort series at all and client-side * needs series sorted by the same criteria used for sorting display sets. */ _proto.sortSeriesByDisplaySets = function () { function sortSeriesByDisplaySets() { var _this3 = this; // Object for mapping display sets' index by seriesInstanceUid var displaySetsMapping = {}; // Loop through each display set to create the mapping this.forEachDisplaySet(function (displaySet, index) { if (!(displaySet instanceof ImageSet)) { throw new OHIFError("StudyMetadata::sortSeriesByDisplaySets display set at index " + index + " is not an instance of ImageSet"); } // In case of multiframe studies, just get the first index occurence if (displaySetsMapping[displaySet.seriesInstanceUid] === void 0) { displaySetsMapping[displaySet.seriesInstanceUid] = index; } }); // Clone of actual series var actualSeries = this.getSeries(); actualSeries.forEach(function (series, index) { if (!(series instanceof SeriesMetadata)) { throw new OHIFError("StudyMetadata::sortSeriesByDisplaySets series at index " + index + " is not an instance of SeriesMetadata"); } // Get the new series index var seriesIndex = displaySetsMapping[series.getSeriesInstanceUID()]; // Update the series object with the new series position _this3._series[seriesIndex] = series; }); } return sortSeriesByDisplaySets; }(); /** * Compares the current study instance with another one. * @param {StudyMetadata} study An instance of the StudyMetadata class. * @returns {boolean} Returns true if both instances refer to the same study. */ _proto.equals = function () { function equals(study) { var self = this; return study === self || study instanceof StudyMetadata && study.getStudyInstanceUID() === self.getStudyInstanceUID(); } return equals; }(); /** * Get the first series of the current study retaining a consistent result across multiple calls. * @return {SeriesMetadata} An instance of the SeriesMetadata class or null if it does not exist. */ _proto.getFirstSeries = function () { function getFirstSeries() { var series = this._firstSeries; if (!(series instanceof SeriesMetadata)) { series = null; var found = this.getSeriesByIndex(0); if (found instanceof SeriesMetadata) { this._firstSeries = found; series = found; } } return series; } return getFirstSeries; }(); /** * Get the first instance of the current study retaining a consistent result across multiple calls. * @return {InstanceMetadata} An instance of the InstanceMetadata class or null if it does not exist. */ _proto.getFirstInstance = function () { function getFirstInstance() { var instance = this._firstInstance; if (!(instance instanceof InstanceMetadata)) { instance = null; var firstSeries = this.getFirstSeries(); if (firstSeries instanceof SeriesMetadata) { var found = firstSeries.getFirstInstance(); if (found instanceof InstanceMetadata) { this._firstInstance = found; instance = found; } } } return instance; } return getFirstInstance; }(); /** * Search the associated series to find an specific instance using the supplied callback as criteria. * The callback is passed two arguments: instance (a InstanceMetadata instance) and index (the integer * index of the instance within the current series) * @param {function} callback The callback function which will be invoked for each instance instance. * @returns {Object} Result object containing series (SeriesMetadata) and instance (InstanceMetadata) * objects or an empty object if not found. */ _proto.findSeriesAndInstanceByInstance = function () { function findSeriesAndInstanceByInstance(callback) { var result; if (Metadata.isValidCallback(callback)) { var instance; var series = this._series.find(function (series) { instance = series.findInstance(callback); return instance instanceof InstanceMetadata; }); // No series found if (series instanceof SeriesMetadata) { result = { series: series, instance: instance }; } } return result || {}; } return findSeriesAndInstanceByInstance; }(); /** * Find series by instance using the supplied callback as criteria. The callback is passed * two arguments: instance (a InstanceMetadata instance) and index (the integer index of * the instance within its series) * @param {function} callback The callback function which will be invoked for each instance. * @returns {SeriesMetadata|undefined} If a series is found based on callback criteria it * returns a SeriesMetadata. "undefined" is returned otherwise */ _proto.findSeriesByInstance = function () { function findSeriesByInstance(callback) { var result = this.findSeriesAndInstanceByInstance(callback); return result.series; } return findSeriesByInstance; }(); /** * Find an instance using the supplied callback as criteria. The callback is passed * two arguments: instance (a InstanceMetadata instance) and index (the integer index of * the instance within its series) * @param {function} callback The callback function which will be invoked for each instance. * @returns {InstanceMetadata|undefined} If an instance is found based on callback criteria it * returns a InstanceMetadata. "undefined" is returned otherwise */ _proto.findInstance = function () { function findInstance(callback) { var result = this.findSeriesAndInstanceByInstance(callback); return result.instance; } return findInstance; }(); return StudyMetadata; }(Metadata); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"StudySummary.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/metadata/StudySummary.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); module.export({ StudySummary: function () { return StudySummary; } }); var Metadata; module.watch(require("./Metadata"), { Metadata: function (v) { Metadata = v; } }, 0); var OHIFError; module.watch(require("../OHIFError"), { OHIFError: function (v) { OHIFError = v; } }, 1); var DICOMTagDescriptions; module.watch(require("../../DICOMTagDescriptions"), { DICOMTagDescriptions: function (v) { DICOMTagDescriptions = v; } }, 2); /** * Constants */ var STUDY_INSTANCE_UID = 'x0020000d'; /** * Class Definition */ var StudySummary = /*#__PURE__*/ function (_Metadata) { (0, _inheritsLoose2.default)(StudySummary, _Metadata); function StudySummary(tagMap, attributeMap, uid) { var _this; // Call the superclass constructor passing an plain object with no prototype to be used as the main "_data" attribute. var _data = Object.create(null); _this = _Metadata.call(this, _data, uid) || this; // Initialize internal tag map if first argument is given. if (tagMap !== void 0) { _this.addTags(tagMap); } // Initialize internal property map if second argument is given. if (attributeMap !== void 0) { _this.setCustomAttributes(attributeMap); } return _this; } var _proto = StudySummary.prototype; _proto.getStudyInstanceUID = function () { function getStudyInstanceUID() { // This method should return null if StudyInstanceUID is not available to keep compatibility StudyMetadata API return this.getTagValue(STUDY_INSTANCE_UID) || null; } return getStudyInstanceUID; }(); /** * Append tags to internal tag map. * @param {Object} tagMap An object whose own properties will be used as tag values and appended to internal tag map. */ _proto.addTags = function () { function addTags(tagMap) { var _hasOwn = Object.prototype.hasOwnProperty; var _data = this._data; for (var tag in meteorBabelHelpers.sanitizeForInObject(tagMap)) { if (_hasOwn.call(tagMap, tag)) { var description = DICOMTagDescriptions.find(tag); // When a description is available, use its tag as internal key... if (description) { _data[description.tag] = tagMap[tag]; } else { _data[tag] = tagMap[tag]; } } } } return addTags; }(); _proto.tagExists = function () { function tagExists(tagName) { var _data = this._data; var description = DICOMTagDescriptions.find(tagName); if (description) { return description.tag in _data; } return tagName in _data; } return tagExists; }(); _proto.getTagValue = function () { function getTagValue(tagName) { var _data = this._data; var description = DICOMTagDescriptions.find(tagName); if (description) { return _data[description.tag]; } return _data[tagName]; } return getTagValue; }(); return StudySummary; }(Metadata); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"WadoRsMetaDataBuilder.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/metadata/WadoRsMetaDataBuilder.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ WadoRsMetaDataBuilder: function () { return WadoRsMetaDataBuilder; } }); var WadoRsMetaDataBuilder = /*#__PURE__*/ function () { function WadoRsMetaDataBuilder() { this.tags = {}; } var _proto = WadoRsMetaDataBuilder.prototype; _proto.addTag = function () { function addTag(tag, value, multi) { this.tags[tag] = { tag: tag, value: value, multi: multi }; return this; } return addTag; }(); _proto.toJSON = function () { function toJSON() { var _this = this; var json = {}; var keys = Object.keys(this.tags); keys.forEach(function (key) { if (!_this.tags.hasOwnProperty(key)) { return; } var tag = _this.tags[key]; var multi = !!tag.multi; var value = tag.value; if (value == null || value.length === 1 && value[0] == null) { return; } if (typeof value === 'string' && multi) { value = value.split('\\'); } if (!_.isArray(value)) { value = [value]; } json[key] = { Value: value }; }); return json; } return toJSON; }(); return WadoRsMetaDataBuilder; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }},"plugins":{"OHIFPlugin.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/plugins/OHIFPlugin.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var module1 = module; module1.export({ OHIFPlugin: function () { return OHIFPlugin; } }); var OHIFPlugin = /*#__PURE__*/ function () { // TODO: this class is still under development and will // likely change in the near future function OHIFPlugin() { this.name = "Unnamed plugin"; this.description = "No description available"; } // load an individual script URL OHIFPlugin.loadScript = function () { function loadScript(scriptURL) { var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "text/javascript"; return new Promise(function (resolve, reject) { var head = document.getElementsByTagName("head")[0]; var script = document.createElement("script"); script.onload = function () { head.removeChild(script); resolve(); }; script.onerror = reject; script.src = scriptURL; script.type = type; script.async = false; head.appendChild(script); }); } return loadScript; }(); // reload all the dependency scripts and also // the main plugin script url. OHIFPlugin.reloadPlugin = function () { function reloadPlugin(plugin) { var _this = this; if (plugin.scriptURLs && plugin.scriptURLs.length) { plugin.scriptURLs.forEach(function (scriptURL) { _this.loadScript(scriptURL); }); } // TODO: Later we should probably merge script and module URLs if (plugin.moduleURLs && plugin.moduleURLs.length) { plugin.moduleURLs.forEach(function (moduleURLs) { _this.loadScript(moduleURLs, "module"); }); } var scriptURL = plugin.url; if (plugin.allowCaching === false) { scriptURL += "?" + performance.now(); } var type = plugin.module === true ? 'module' : 'text/javascript'; console.warn("Calling loadScript for " + plugin.name); console.time("loadScript " + plugin.name); this.loadScript(scriptURL, type).then(function (script) { console.timeEnd("loadScript " + plugin.name); var entryPointFunction = OHIF.plugins.entryPoints[plugin.name]; if (entryPointFunction) { entryPointFunction(); } else { throw new Error("No entry point found for " + plugin.name); } }, function (error) { throw new Error(error); }); } return reloadPlugin; }(); return OHIFPlugin; }(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"ViewportPlugin.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/plugins/ViewportPlugin.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); module.export({ ViewportPlugin: function () { return ViewportPlugin; } }); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 0); var Tracker; module.watch(require("meteor/tracker"), { Tracker: function (v) { Tracker = v; } }, 1); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 2); var OHIFPlugin; module.watch(require("./OHIFPlugin"), { OHIFPlugin: function (v) { OHIFPlugin = v; } }, 3); var ViewportPlugin = /*#__PURE__*/ function (_OHIFPlugin) { (0, _inheritsLoose2.default)(ViewportPlugin, _OHIFPlugin); function ViewportPlugin(name) { var _this; _this = _OHIFPlugin.call(this) || this; _this.name = name; _this._destroyed = false; _this._setupListeners(); return _this; } /** * Retrieve a Display Set for a specific viewport by viewport index, * if one is already displayed in the viewport. * * @static * @param {Number} viewportIndex * @return {undefined|ImageSet} */ ViewportPlugin.getDisplaySet = function () { function getDisplaySet(viewportIndex) { // TODO: Move layoutManager from viewerbase to viewer var layoutManager = OHIF.viewerbase.layoutManager; var viewportData = layoutManager.viewportData[viewportIndex]; var studyInstanceUid = viewportData.studyInstanceUid, displaySetInstanceUid = viewportData.displaySetInstanceUid; var studyMetadata = OHIF.viewer.StudyMetadataList.findBy({ studyInstanceUID: studyInstanceUid }); return studyMetadata.findDisplaySet(function (displaySet) { return displaySet.displaySetInstanceUid === displaySetInstanceUid; }); } return getDisplaySet; }(); /** * Set up the viewport using the plugin. * * This should be implemented by the child class. * * @abstract * * @param {HTMLElement} div * @param {ImageSet} displaySet * @param {Object} viewportDetails */ var _proto = ViewportPlugin.prototype; _proto.setupViewport = function () { function setupViewport(div, displaySet, viewportDetails) { throw new Error('You must override this method!'); } return setupViewport; }(); /** * Switch a single viewport to use the current ViewportPlugin * * @param {Number} viewportIndex The viewport to switch to the current plugin type */ _proto.setViewportToPlugin = function () { function setViewportToPlugin(viewportIndex) { if (!this.name) { throw new Error('ViewportPlugin subclasses must have a name'); } var layoutManager = OHIF.viewerbase.layoutManager; var viewportData = layoutManager.viewportData[viewportIndex]; if (viewportData.plugin === this.name) { OHIF.log.info("setViewportToPlugin: Viewport " + viewportIndex + " already set to plugin " + this.name); } viewportData.plugin = this.name; layoutManager.rerenderViewportWithNewDisplaySet(viewportIndex, viewportData); } return setViewportToPlugin; }(); /** * Runs 'setupViewport' for the ViewportPlugin on all viewports which should * be rendered by this plugin, but have not yet been initialized. Viewports * which already contain contents are skipped. * * @private */ _proto._initEmptyPluginViewports = function () { function _initEmptyPluginViewports() { var _this2 = this; if (!this.name) { throw new Error('ViewportPlugin subclasses must have a name'); } // Find all Viewport HTMLElements currently using this plugin var pluginDivs = Array.from(document.querySelectorAll(".viewport-plugin-" + this.name)); // If there are no Viewports using this plugin, stop here if (!pluginDivs.length) { return; } var emptyPluginDivs = pluginDivs.filter(function (div) { // Keep only divs owned by the plugin which have no contents return div.innerHTML.trim() === ''; }); OHIF.log.info(this.name + ": Initializing " + emptyPluginDivs.length + " viewports"); // Retrieve the list of all viewports, so we can figure out the viewport details var allViewports = Array.from(document.querySelectorAll('.viewportContainer')); var layoutManager = OHIF.viewerbase.layoutManager; emptyPluginDivs.forEach(function (div) { // Identify the Viewport index, and any display set that is currently // hung in the viewport var viewportIndex = allViewports.indexOf(div.parentNode); var viewportData = layoutManager.viewportData[viewportIndex]; var displaySet = ViewportPlugin.getDisplaySet(viewportIndex); // Use the plugin's setupViewport function to render the contents // of this viewport. _this2.setupViewport(div, viewportData, displaySet); }); } return _initEmptyPluginViewports; }(); /** * Listen for changes to the viewport layout which would necessitate a * rerendering of the viewports. When this happens, re-render all viewports * which are using this plugin. * * @private */ _proto._setupListeners = function () { function _setupListeners() { var _this3 = this; if (!this.name) { throw new Error('ViewportPlugin subclasses must have a name'); } console.warn("_setupListeners: " + this.name); // TODO: Stop using Meteor's reactivity here Tracker.autorun(function (computation) { var random = Session.get('LayoutManagerUpdated'); console.warn("LayoutManagerUpdated: " + _this3.name + ": " + random); // Bail out if this is the first time the autorun // executes (i.e. when it is being defined). // // Note: This has to be checked after the dependency on the // Session variable above, or the reactive dependency will not // be established. if (computation.firstRun === true) { return; } // In case we need to disable the use // of this plugin, we can also stop the // reactive computation by setting // this.destroyed to true. if (_this3._destroyed === true) { computation.stop(); } // Identify all viewports which should be // rendered by the ViewportPlugin, and render // them. _this3._initEmptyPluginViewports(); }); } return _setupListeners; }(); /** * Stop listening for changes to the viewport layout in order to * automatically rerender viewports setup for use by this plugin. */ _proto.stopListeners = function () { function stopListeners() { this._destroyed = true; } return stopListeners; }(); return ViewportPlugin; }(OHIFPlugin); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"index.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/classes/plugins/index.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); var OHIFPlugin; module.watch(require("./OHIFPlugin"), { OHIFPlugin: function (v) { OHIFPlugin = v; } }, 1); var ViewportPlugin; module.watch(require("./ViewportPlugin"), { ViewportPlugin: function (v) { ViewportPlugin = v; } }, 2); // Each plugin registers an entry point function to be called // when the loading is complete. var plugins = { OHIFPlugin: OHIFPlugin, ViewportPlugin: ViewportPlugin, entryPoints: {} }; // TODO: When we reorganize the packages, we should figure out where to put this. OHIF.plugins = plugins; module.exportDefault(plugins); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }}},"helpers":{"capitalizeFirstLetter.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/capitalizeFirstLetter.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); /** * A global Blaze UI helper to capitalizes the first letter of an input String * * Credit to: * * http://stackoverflow.com/questions/1026069/capitalize-the-first-letter-of-string-in-javascript */ Blaze.registerHelper('capitalizeFirstLetter', function (context) { if (!context) { return; } return context.charAt(0).toUpperCase() + context.slice(1); }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"formatDA.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/formatDA.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ formatDA: function () { return formatDA; } }); var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); var moment; module.watch(require("meteor/momentjs:moment"), { moment: function (v) { moment = v; } }, 1); /** * A global Blaze UI helper function to format DICOM Dates using the Moment library */ var formatDA = function (context, format, options) { if (!context) { return undefined; } var dateAsMoment = moment(context, "YYYYMMDD"); var strFormat = "MMM D, YYYY"; if (options) { strFormat = format; } return dateAsMoment.format(strFormat); }; // Check if global helper already exists to not override it if (!Blaze._getGlobalHelper('formatDA')) { Blaze.registerHelper('formatDA', formatDA); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"formatJSDate.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/formatJSDate.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); var moment; module.watch(require("meteor/momentjs:moment"), { moment: function (v) { moment = v; } }, 1); /** * A global Blaze UI helper function to format JavaScript Dates using the Moment library */ Blaze.registerHelper('formatJSDate', function (context, format, options) { if (!context) { return; } var dateAsMoment = moment(new Date(context)); var strFormat = 'MMM D, YYYY'; if (options) { strFormat = format; } return dateAsMoment.format(strFormat); }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"formatNumberPrecision.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/formatNumberPrecision.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); /** * A global Blaze UI helper to format a float value to a specified precision */ Blaze.registerHelper('formatNumberPrecision', function (context, precision) { if (context != null) { return parseFloat(context).toFixed(precision); } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"formatPN.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/formatPN.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ formatPN: function () { return formatPN; } }); var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); /** * Formats a patient name for display purposes */ var formatPN = function (context) { if (!context) { return; } // Convert the first ^ to a ', '. String.replace() only affects // the first appearance of the character. var commaBetweenFirstAndLast = context.replace('^', ', '); // Replace any remaining '^' characters with spaces var cleaned = commaBetweenFirstAndLast.replace(/\^/g, ' '); // Trim any extraneous whitespace return cleaned.trim(); }; /** * A global Blaze UI helper to format a patient name for display purposes */ // Check if global helper already exists to not override it if (!Blaze._getGlobalHelper('formatPN')) { Blaze.registerHelper('formatPN', formatPN); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"formatTM.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/formatTM.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ formatTM: function () { return formatTM; } }); var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); var moment; module.watch(require("meteor/momentjs:moment"), { moment: function (v) { moment = v; } }, 1); /** * A global Blaze UI helper to format a DICOM Time for display using the Moment library */ var formatTM = function (context, options) { if (!context) { return; } // DICOM Time is stored as HHmmss.SSS, where: // HH 24 hour time: // m mm 0..59 Minutes // s ss 0..59 Seconds // S SS SSS 0..999 Fractional seconds // // See MomentJS: http://momentjs.com/docs/#/parsing/string-format/ var dateTime = moment(context, 'HHmmss.SSS'); var format = "HH:mm:ss"; if (options && options.format) { format = options.format; } return dateTime.format(format); }; // Check if global helper already exists to not override it if (!Blaze._getGlobalHelper('formatTM')) { Blaze.registerHelper('formatTM', formatTM); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"getUsername.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/getUsername.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Meteor; module.watch(require("meteor/meteor"), { Meteor: function (v) { Meteor = v; } }, 0); var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 1); /** * Helper for retrieving username given userId */ Blaze.registerHelper('getUsername', function (userId) { var user = Meteor.users.findOne({ userId: userId }); if (user && user.name) { return user.name; } }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"ifTypeIs.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/ifTypeIs.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); /** * Helper for checking datatype of a variable */ Blaze.registerHelper('ifTypeIs', function (value, match, attributeName) { if ((0, _typeof2.default)(value) === match) { return attributeName; } return ''; }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"inc.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/inc.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); Blaze.registerHelper('inc', function (value) { return parseInt(value) + 1; }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"index.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/index.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ helpers: function () { return helpers; } }); var isTouchDevice; module.watch(require("./isTouchDevice"), { isTouchDevice: function (v) { isTouchDevice = v; } }, 0); var formatPN; module.watch(require("./formatPN"), { formatPN: function (v) { formatPN = v; } }, 1); var formatDA; module.watch(require("./formatDA"), { formatDA: function (v) { formatDA = v; } }, 2); var formatTM; module.watch(require("./formatTM"), { formatTM: function (v) { formatTM = v; } }, 3); module.watch(require("./formatJSDate")); module.watch(require("./jsDateFromNow")); module.watch(require("./formatNumberPrecision")); module.watch(require("./inc")); module.watch(require("./isDisplaySetActive")); module.watch(require("./getUsername")); module.watch(require("./capitalizeFirstLetter")); module.watch(require("./objectToPairs")); module.watch(require("./objectEach")); module.watch(require("./ifTypeIs")); module.watch(require("./prettyPrintStringify")); module.watch(require("./sorting")); module.watch(require("./studyThumbnails")); /** * Exposed interface... */ var helpers = { isTouchDevice: isTouchDevice, formatPN: formatPN, formatDA: formatDA, formatTM: formatTM }; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"isDisplaySetActive.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/isDisplaySetActive.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 1); var $; module.watch(require("meteor/jquery"), { $: function (v) { $ = v; } }, 2); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 3); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 4); module.watch(require("meteor/ohif:viewerbase")); /** * Boolean helper to identify if a series instance is active in some viewport */ Template.registerHelper('isDisplaySetActive', function (displaySetInstanceUid, viewportIndex) { // Run this computation every time the viewports are updated Session.get('LayoutManagerUpdated'); // Stop here if layoutManager is not defined yet if (!OHIF.viewerbase.layoutManager) { return; } // Check if the display set is current visible in any of the layout // manager's displayed viewports. Note that we have to check the // onscreen number of viewports here, since the layout manager will // keep the viewport data of old viewports, even after the layout is changed. // // This behaviour is intentional. If the user displays four viewports, then assigns // display sets to them, and then switches to / from another layout configuration, // we don't want them to lose their specified viewports. var result = false; if (_.isUndefined(viewportIndex)) { // Get the number of viewports that are currently displayed // (Note, viewportData may have more entries!) var currentNumberOfViewports = OHIF.viewerbase.layoutManager.getNumberOfViewports(); // Loop through the viewport data up until the currently displayed // number of viewports var viewportData = OHIF.viewerbase.layoutManager.viewportData; for (var i = 0; i < currentNumberOfViewports; i++) { var data = viewportData[i]; // If the display set is displayed in this viewport and is active, stop here if (data && data.displaySetInstanceUid === displaySetInstanceUid) { result = true; break; } } } else { var _data = OHIF.viewerbase.layoutManager.viewportData[viewportIndex]; // If the display set is displayed in this viewport, stop here if (_data && _data.displaySetInstanceUid === displaySetInstanceUid) { result = true; } } return result; }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"isTouchDevice.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/isTouchDevice.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ isTouchDevice: function () { return isTouchDevice; } }); var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); /** * Helper function to determine if the current client devices * is touch-capable. This can be used to modify certain aspects of the UI. * * The check may not work on all devices! * * @returns {boolean} true if the client device is touch-capable, false otherwise */ var isTouchDevice = function () { return 'ontouchstart' in window || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; }; /** * Blaze helper for checking if the current device is touch capable * * @returns {boolean} true if the client device is touch-capable, false otherwise */ Blaze.registerHelper('isTouchDevice', isTouchDevice); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"jsDateFromNow.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/jsDateFromNow.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); var Session; module.watch(require("meteor/session"), { Session: function (v) { Session = v; } }, 1); var moment; module.watch(require("meteor/momentjs:moment"), { moment: function (v) { moment = v; } }, 2); /** * A global Blaze UI helper function to format JavaScript Dates using the Moment library */ Blaze.registerHelper('jsDateFromNow', function (context, format, options) { if (!context) { return; } Session.get('timeAgoVariable'); var dateAsMoment = moment(new Date(context)); return dateAsMoment.fromNow(); }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"objectEach.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/objectEach.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 1); Blaze.registerHelper('objectEach', function (object) { // http://stackoverflow.com/questions/30234732/how-to-print-key-and-values-in-meteor-template return _.map(object, function (value, key) { return _.extend({ key: key }, value); }); }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"objectToPairs.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/objectToPairs.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 1); Blaze.registerHelper('objectToPairs', function (object) { // http://stackoverflow.com/questions/30234732/how-to-print-key-and-values-in-meteor-template return _.map(object, function (value, key) { return { key: key, value: value }; }); }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"prettyPrintStringify.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/prettyPrintStringify.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Blaze; module.watch(require("meteor/blaze"), { Blaze: function (v) { Blaze = v; } }, 0); /** * A global Blaze UI helper to Stringify a JavaScript object * * Credit to: * * http://stackoverflow.com/questions/1026069/capitalize-the-first-letter-of-string-in-javascript */ Blaze.registerHelper('prettyPrintStringify', function (context) { if (!context) { return; } var string = JSON.stringify(context, null, 2); string = string.replace(/['"]+/g, ''); string = string.replace('{', ''); string = string.replace('}', ''); string = string.replace(',', '\n'); return string; }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"sorting.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/sorting.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 1); /** * Global Blaze UI helper to sort array elements * by an array element's property (property) or deep object property (property.childProperty) * Sorts ascending as default */ Template.registerHelper('sort', function (array, sortBy, sortType) { if (!sortBy) { return array; } // To keep the order for the same values of the field which is used to sort: // 1. Group the array by the field // 2. Sort the grouped array // 3. Ungroup the sorted array var groupedArray = _.groupBy(array, function (element) { if (sortBy) { var groupingElement = getKeyValue(element, sortBy); if (groupingElement) { return groupingElement; } } return element; }); var sortedArray = _.sortBy(groupedArray, function (element) { if (sortBy) { var sortingElement = getKeyValue(element[0], sortBy); if (sortingElement) { return sortingElement; } } return element; }); if (sortType === 'desc') { return _.flatten(sortedArray.reverse(), true); } return _.flatten(sortedArray, true); }); function getKeyValue(object, keyPath) { keyPath = keyPath.split('.'); for (var i = 0; i < keyPath.length; i++) { if (object && _.has(object, keyPath[i])) { object = object[keyPath[i]]; } else { return undefined; } } return object; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"studyThumbnails.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/lib/helpers/studyThumbnails.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var Template; module.watch(require("meteor/templating"), { Template: function (v) { Template = v; } }, 0); var _; module.watch(require("meteor/underscore"), { _: function (v) { _ = v; } }, 1); /** * A global Blaze UI helper to get the thumbnails for the given study */ Template.registerHelper('studyThumbnails', function (study) { if (!study) { return; } // Find the study's stacks var stacks = study.displaySets; // Defines the resulting thumbnails list var thumbnails = []; // Iterate over the stacks and add one by one with its index _.each(stacks, function (stack, thumbnailIndex) { thumbnails.push({ thumbnailIndex: thumbnailIndex, stack: stack }); }); return thumbnails; }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }}}},"main.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/main.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var module1 = module; module1.export({ OHIF: function () { return OHIF; }, Viewerbase: function () { return Viewerbase; } }); var OHIF, Viewerbase; module1.watch(require("./namespace.js"), { OHIF: function (v) { OHIF = v; }, Viewerbase: function (v) { Viewerbase = v; } }, 0); module1.watch(require("./client/")); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// },"namespace.js":function(require,exports,module){ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/namespace.js // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // module.export({ OHIF: function () { return OHIF; }, Viewerbase: function () { return Viewerbase; } }); var OHIF; module.watch(require("meteor/ohif:core"), { OHIF: function (v) { OHIF = v; } }, 0); /** * Create Viewerbase namespace */ var Viewerbase = {}; /** * Append Viewerbase namespace to OHIF namespace */ OHIF.viewerbase = Viewerbase; /** * Export relevant objects */ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// }}}}},{ "extensions": [ ".js", ".json", ".styl", ".html" ] }); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // packages/ohif_viewerbase/client/compatibility/dialogPolyfill.js // // This file is in bare mode and is not in its own closure. // // // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // var dialogPolyfill = (function() { var supportCustomEvent = window.CustomEvent; if (!supportCustomEvent || typeof supportCustomEvent == "object") { supportCustomEvent = function CustomEvent(event, x) { x = x || {}; var ev = document.createEvent('CustomEvent'); ev.initCustomEvent(event, !!x.bubbles, !!x.cancelable, x.detail || null); return ev; }; supportCustomEvent.prototype = window.Event.prototype; } /** * Finds the nearest from the passed element. * * @param {Element} el to search from * @param {HTMLDialogElement} dialog found */ function findNearestDialog(el) { while (el) { if (el.nodeName == 'DIALOG') { return el; } el = el.parentElement; } return null; } var dialogPolyfill = {}; dialogPolyfill.reposition = function(element) { var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2; element.style.top = Math.max(0, topValue) + 'px'; element.dialogPolyfillInfo.isTopOverridden = true; }; dialogPolyfill.inNodeList = function(nodeList, node) { for (var i = 0; i < nodeList.length; ++i) { if (nodeList[i] == node) return true; } return false; }; dialogPolyfill.isInlinePositionSetByStylesheet = function(element) { for (var i = 0; i < document.styleSheets.length; ++i) { var styleSheet = document.styleSheets[i]; var cssRules = null; // Some browsers throw on cssRules. try { cssRules = styleSheet.cssRules; } catch (e) {} if (!cssRules) continue; for (var j = 0; j < cssRules.length; ++j) { var rule = cssRules[j]; var selectedNodes = null; // Ignore errors on invalid selector texts. try { selectedNodes = document.querySelectorAll(rule.selectorText); } catch(e) {} if (!selectedNodes || !dialogPolyfill.inNodeList(selectedNodes, element)) continue; var cssTop = rule.style.getPropertyValue('top'); var cssBottom = rule.style.getPropertyValue('bottom'); if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto')) return true; } } return false; }; dialogPolyfill.needsCentering = function(dialog) { var computedStyle = window.getComputedStyle(dialog); if (computedStyle.position != 'absolute') { return false; } // We must determine whether the top/bottom specified value is non-auto. In // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but // Firefox returns the used value. So we do this crazy thing instead: check // the inline style and then go through CSS rules. if ((dialog.style.top != 'auto' && dialog.style.top != '') || (dialog.style.bottom != 'auto' && dialog.style.bottom != '')) return false; return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog); }; dialogPolyfill.showDialog = function(isModal) { if (this.open) { throw 'InvalidStateError: showDialog called on open dialog'; } this.open = true; // TODO: should be a getter mapped to attribute this.setAttribute('open', 'open'); if (isModal) { // Find element with `autofocus` attribute or first form control var first_form_ctrl = null; var autofocus = null; var findElementToFocus = function(root) { if (!root.children) { return; } for (var i = 0; i < root.children.length; i++) { var elem = root.children[i]; if (first_form_ctrl === null && !elem.disabled && ( elem.nodeName == 'BUTTON' || elem.nodeName == 'INPUT' || elem.nodeName == 'KEYGEN' || elem.nodeName == 'SELECT' || elem.nodeName == 'TEXTAREA')) { first_form_ctrl = elem; } if (elem.autofocus) { autofocus = elem; return; } findElementToFocus(elem); if (autofocus !== null) return; } }; findElementToFocus(this); if (autofocus !== null) { autofocus.focus(); } else if (first_form_ctrl !== null) { first_form_ctrl.focus(); } } if (dialogPolyfill.needsCentering(this)) dialogPolyfill.reposition(this); if (isModal) { this.dialogPolyfillInfo.modal = true; dialogPolyfill.dm.pushDialog(this); } // IE sometimes complains when calling .focus() that it // "Can't move focus to the control because it is invisible, not enabled, or of a type that does not accept the focus." try { if (autofocus !== null) { autofocus.focus(); } else if (first_form_ctrl !== null) { first_form_ctrl.focus(); } } catch(e) {} this.style.zoom = 1; }; dialogPolyfill.close = function(retval) { if (!this.open && !window.HTMLDialogElement) { // Native implementations will set .open to false, so ignore this error. throw 'InvalidStateError: close called on closed dialog'; } this.open = false; this.removeAttribute('open'); // Leave returnValue untouched in case it was set directly on the element if (typeof retval != 'undefined') { this.returnValue = retval; } // This won't match the native exactly because if the user sets top // on a centered polyfill dialog, that top gets thrown away when the dialog is // closed. Not sure it's possible to polyfill this perfectly. if (this.dialogPolyfillInfo.isTopOverridden) { this.style.top = 'auto'; } if (this.dialogPolyfillInfo.modal) { dialogPolyfill.dm.removeDialog(this); } // Triggering "close" event for any attached listeners on the var event; if (document.createEvent) { event = document.createEvent('HTMLEvents'); event.initEvent('close', true, true); } else { event = new Event('close'); } this.dispatchEvent(event); return this.returnValue; }; dialogPolyfill.registerDialog = function(element) { if (element.show) { // console.warn("This browser already supports , the polyfill " + // "may not work correctly."); } element.show = dialogPolyfill.showDialog.bind(element, false); element.showModal = dialogPolyfill.showDialog.bind(element, true); element.close = dialogPolyfill.close.bind(element); element.dialogPolyfillInfo = {}; element.open = false; }; // The overlay is used to simulate how a modal dialog blocks the document. The // blocking dialog is positioned on top of the overlay, and the rest of the // dialogs on the pending dialog stack are positioned below it. In the actual // implementation, the modal dialog stacking is controlled by the top layer, // where z-index has no effect. var TOP_LAYER_ZINDEX = 100000; var MAX_PENDING_DIALOGS = 100000; dialogPolyfill.DialogManager = function() { this.pendingDialogStack = []; this.overlay = document.createElement('div'); this.overlay.style.width = '100%'; this.overlay.style.height = '100%'; this.overlay.style.position = 'fixed'; this.overlay.style.left = '0px'; this.overlay.style.top = '0px'; this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)'; this.focusPageLast = this.createFocusable(); this.overlay.appendChild(this.focusPageLast); this.overlay.addEventListener('click', function(e) { var redirectedEvent = document.createEvent('MouseEvents'); redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget); document.body.dispatchEvent(redirectedEvent); }); // TODO: Only install when any dialogs are open. document.addEventListener('submit', function(ev) { var method = ev.target.getAttribute('method'); method = method ? method.toLowerCase() : ''; if (method != 'dialog') { return; } ev.preventDefault(); var dialog = findNearestDialog(ev.target); if (!dialog) { return; } // FIXME: The original event doesn't contain the INPUT element used to // submit the form (if any). Look in some possible places. var returnValue; var cands = [document.activeElement, ev.explicitOriginalTarget]; cands.some(function(cand) { if (cand && cand.nodeName == 'INPUT' && cand.form == ev.target) { returnValue = cand.value; return true; } }); dialog.close(returnValue); }, true); }; dialogPolyfill.DialogManager.prototype.createFocusable = function(tabIndex) { var span = document.createElement('span'); span.tabIndex = tabIndex || 0; span.style.opacity = 0; span.style.position = 'static'; return span; }; dialogPolyfill.DialogManager.prototype.blockDocument = function() { if (!document.body.contains(this.overlay)) { document.body.appendChild(this.overlay); // On Safari/Mac (and possibly other browsers), the documentElement is // not focusable. This is required for modal dialogs as it is the first // element to be hit by a tab event, and further tabs are redirected to // the most visible dialog. if (this.needsDocumentElementFocus === undefined) { document.documentElement.focus(); this.needsDocumentElementFocus = (document.activeElement != document.documentElement); } if (this.needsDocumentElementFocus) { document.documentElement.tabIndex = 1; } } }; dialogPolyfill.DialogManager.prototype.unblockDocument = function() { document.body.removeChild(this.overlay); if (this.needsDocumentElementFocus) { // TODO: Restore the previous tabIndex, rather than clearing it. document.documentElement.tabIndex = ''; } }; dialogPolyfill.DialogManager.prototype.updateStacking = function() { if (this.pendingDialogStack.length == 0) { this.unblockDocument(); return; } this.blockDocument(); var zIndex = TOP_LAYER_ZINDEX; for (var i = 0; i < this.pendingDialogStack.length; i++) { if (i == this.pendingDialogStack.length - 1) this.overlay.style.zIndex = zIndex++; var dialog = this.pendingDialogStack[i]; dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++; dialog.style.zIndex = zIndex++; } }; dialogPolyfill.DialogManager.prototype.handleKey = function(event) { var dialogCount = this.pendingDialogStack.length; if (dialogCount == 0) { return; } var dialog = this.pendingDialogStack[dialogCount - 1]; var pfi = dialog.dialogPolyfillInfo; switch (event.keyCode) { case 9: /* tab */ var activeElement = document.activeElement; var forward = !event.shiftKey; if (forward) { // Tab forward, so look for document or fake last focus element. if (activeElement == document.documentElement || activeElement == document.body || activeElement == pfi.backdrop) { pfi.focusFirst.focus(); } else if (activeElement == pfi.focusLast) { // TODO: Instead of wrapping to focusFirst, escape to browser chrome. pfi.focusFirst.focus(); } } else { // Tab backwards, so look for fake first focus element. if (activeElement == pfi.focusFirst) { // TODO: Instead of wrapping to focusLast, escape to browser chrome. pfi.focusLast.focus(); } else if (activeElement == this.focusPageLast) { // The focus element is at the end of the page (e.g., shift-tab from // the window chrome): move current focus to the last element in the // dialog instead. pfi.focusLast.focus(); } } break; case 27: /* esc */ event.preventDefault(); event.stopPropagation(); var cancelEvent = new supportCustomEvent('cancel', { bubbles: false, cancelable: true }); if (dialog.dispatchEvent(cancelEvent)) { dialog.close(); } break; } }; dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) { if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) { throw "Too many modal dialogs"; } var backdrop = document.createElement('div'); backdrop.className = 'backdrop'; var clickEventListener = function(e) { var redirectedEvent = document.createEvent('MouseEvents'); redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget); dialog.dispatchEvent(redirectedEvent); }; backdrop.addEventListener('click', clickEventListener); dialog.parentNode.insertBefore(backdrop, dialog.nextSibling); dialog.dialogPolyfillInfo.backdrop = backdrop; dialog.dialogPolyfillInfo.clickEventListener = clickEventListener; this.pendingDialogStack.push(dialog); this.updateStacking(); dialog.dialogPolyfillInfo.focusFirst = this.createFocusable(); dialog.dialogPolyfillInfo.focusLast = this.createFocusable(); dialog.appendChild(dialog.dialogPolyfillInfo.focusLast); dialog.insertBefore( dialog.dialogPolyfillInfo.focusFirst, dialog.firstChild); }; dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) { var index = this.pendingDialogStack.indexOf(dialog); if (index == -1) { return; } this.pendingDialogStack.splice(index, 1); var backdrop = dialog.dialogPolyfillInfo.backdrop; var clickEventListener = dialog.dialogPolyfillInfo.clickEventListener; backdrop.removeEventListener('click', clickEventListener); backdrop.parentNode.removeChild(backdrop); dialog.dialogPolyfillInfo.backdrop = null; dialog.dialogPolyfillInfo.clickEventListener = null; this.updateStacking(); dialog.removeChild(dialog.dialogPolyfillInfo.focusFirst); dialog.removeChild(dialog.dialogPolyfillInfo.focusLast); dialog.dialogPolyfillInfo.focusFirst = null; dialog.dialogPolyfillInfo.focusLast = null; }; dialogPolyfill.dm = new dialogPolyfill.DialogManager(); document.addEventListener('keydown', dialogPolyfill.dm.handleKey.bind(dialogPolyfill.dm)); return dialogPolyfill; })(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// require("/node_modules/meteor/ohif:viewerbase/client/components/basic/layout/template.layout.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/basic/loadingText/template.loadingText.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/basic/errorText/template.errorText.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/basic/removableBackdrop/template.removableBackdrop.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/basic/aboutModal/template.aboutModal.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/basic/aboutModal/aboutModal.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/studyBrowser/studyBrowser/template.studyBrowser.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/studyBrowser/studyBrowser/studyBrowser.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/studyBrowser/thumbnailEntry/template.thumbnailEntry.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/studyBrowser/thumbnailEntry/thumbnailEntry.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/studyBrowser/imageThumbnail/template.imageThumbnail.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/studyBrowser/imageThumbnail/imageThumbnail.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/imageViewerViewport/template.imageViewerViewport.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/imageViewerViewport/imageViewerViewport.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/gridLayout/template.gridLayout.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/gridLayout/gridLayout.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/loadingIndicator/template.loadingIndicator.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/loadingIndicator/loadingIndicator.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/annotationDialogs/template.annotationDialogs.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/annotationDialogs/annotationDialogs.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/viewportOrientationMarkers/template.viewportOrientationMarkers.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/viewportOverlay/template.viewportOverlay.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/viewportOverlay/viewportOverlay.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/viewerMain/template.viewerMain.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/viewerMain/viewerMain.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/toolContextMenu/toolContextMenu.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/imageControls/template.imageControls.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/imageControls/imageControls.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/layoutButton/template.layoutButton.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/layoutButton/layoutButton.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/layoutChooser/template.layoutChooser.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/layoutChooser/layoutChooser.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/cineDialog/template.cineDialog.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/cineDialog/cineDialog.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/downloadDialog/template.downloadDialog.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/downloadDialog/downloadDialog.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/toolbarSectionButton/template.toolbarSectionButton.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/toolbarSectionButton/toolbarSectionButton.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/toolbarSectionTools/template.toolbarSectionTools.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/toolbarSectionTools/toolbarSectionTools.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/userPreferences/template.dialog.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/userPreferences/dialog.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/confirmDeleteDialog/template.confirmDeleteDialog.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/confirmDeleteDialog/confirmDeleteDialog.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/textMarkerDialogs/template.textMarkerDialogs.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/textMarkerDialogs/textMarkerDialogs.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/seriesQuickSwitch/template.seriesQuickSwitch.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/seriesQuickSwitch/seriesQuickSwitch.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/studySeriesQuickSwitch/template.studySeriesQuickSwitch.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/studySeriesQuickSwitch/studySeriesQuickSwitch.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/studyTimepointBrowser/template.studyTimepoint.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/studyTimepointBrowser/studyTimepoint.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/studyTimepointBrowser/template.studyTimepointBrowser.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/studyTimepointBrowser/studyTimepointBrowser.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/studyTimepointBrowser/template.studyTimepointStudy.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/studyTimepointBrowser/studyTimepointStudy.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/windowLevelPresets/template.form.js"); require("/node_modules/meteor/ohif:viewerbase/client/components/viewer/windowLevelPresets/form.js"); var exports = require("/node_modules/meteor/ohif:viewerbase/main.js"); /* Exports */ Package._define("ohif:viewerbase", exports, { dialogPolyfill: dialogPolyfill }); })();