LT-303: adding frame rate value to active viewport so cornerstone tools can work properly (forward not backward). Some code improvements.

This commit is contained in:
Eloízio Salgado 2016-11-08 13:15:09 -02:00 committed by Erik Ziegler
parent be56608208
commit c862c3fa5c

View File

@ -22,17 +22,17 @@ function loadDisplaySetIntoViewport(data, templateData) {
// Get the current element and it's index in the list of all viewports // 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 // The viewport index is often used to store information about a viewport element
var element = data.element; const element = data.element;
var viewportIndex = $('.imageViewerViewport').index(element); const viewportIndex = $('.imageViewerViewport').index(element);
let layoutManager = window.layoutManager; const layoutManager = window.layoutManager;
layoutManager.viewportData = layoutManager.viewportData || {}; layoutManager.viewportData = layoutManager.viewportData || {};
layoutManager.viewportData[viewportIndex] = layoutManager.viewportData[viewportIndex] || {}; layoutManager.viewportData[viewportIndex] = layoutManager.viewportData[viewportIndex] || {};
layoutManager.viewportData[viewportIndex].viewportIndex = viewportIndex; layoutManager.viewportData[viewportIndex].viewportIndex = viewportIndex;
// Get the contentID of the current study list tab, if the viewport is running // Get the contentID of the current study list tab, if the viewport is running
// alongside the study list package // alongside the study list package
var contentId = Session.get('activeContentId'); const contentId = Session.get('activeContentId');
// If the viewer is inside a tab, create an object related to the specified viewport // If the viewer is inside a tab, create an object related to the specified viewport
// This data will be saved so that the tab can be reloaded to the same state after tabs // This data will be saved so that the tab can be reloaded to the same state after tabs
@ -46,17 +46,17 @@ function loadDisplaySetIntoViewport(data, templateData) {
} }
// Create an empty array to populate with image IDs // Create an empty array to populate with image IDs
var imageIds = []; const imageIds = [];
// Loop through the current series and add metadata to the // Loop through the current series and add metadata to the
// Cornerstone meta data provider. This will be used to fill information // Cornerstone meta data provider. This will be used to fill information
// into the viewport overlays, and to calculate reference lines and orientation markers // into the viewport overlays, and to calculate reference lines and orientation markers
var displaySet = data.displaySet; const displaySet = data.displaySet;
var numImages = displaySet.images.length; const numImages = displaySet.images.length;
var imageId; let imageId;
displaySet.images.forEach(function(image, imageIndex) { displaySet.images.forEach((image, imageIndex) => {
var metaData = { const metaData = {
instance: image, instance: image,
series: displaySet, // TODO: Check this series: displaySet, // TODO: Check this
study: data.study, study: data.study,
@ -64,7 +64,7 @@ function loadDisplaySetIntoViewport(data, templateData) {
imageIndex: imageIndex + 1 imageIndex: imageIndex + 1
}; };
var numFrames = image.numFrames; const numFrames = image.numFrames;
if (numFrames > 1) { if (numFrames > 1) {
OHIF.log.info('Multiframe image detected'); OHIF.log.info('Multiframe image detected');
for (var i = 0; i < numFrames; i++) { for (var i = 0; i < numFrames; i++) {
@ -73,7 +73,8 @@ function loadDisplaySetIntoViewport(data, templateData) {
imageIds.push(imageId); imageIds.push(imageId);
addMetaData(imageId, metaData); addMetaData(imageId, metaData);
} }
} else { }
else {
imageId = getImageId(image); imageId = getImageId(image);
imageIds.push(imageId); imageIds.push(imageId);
addMetaData(imageId, metaData); addMetaData(imageId, metaData);
@ -81,7 +82,7 @@ function loadDisplaySetIntoViewport(data, templateData) {
}); });
// Define the current image stack using the newly created image IDs // Define the current image stack using the newly created image IDs
var stack = { const stack = {
currentImageIdIndex: data.currentImageIdIndex || 0, currentImageIdIndex: data.currentImageIdIndex || 0,
imageIds: imageIds imageIds: imageIds
}; };
@ -101,8 +102,7 @@ function loadDisplaySetIntoViewport(data, templateData) {
ViewportLoading[viewportIndex] = imageId; ViewportLoading[viewportIndex] = imageId;
// Enable Cornerstone for the viewport element // Enable Cornerstone for the viewport element
// const options = {
var options = {
renderer: 'webgl' renderer: 'webgl'
}; };
@ -113,33 +113,39 @@ function loadDisplaySetIntoViewport(data, templateData) {
// Get the handler functions that will run when loading has finished or thrown // 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. // an error. These are used to show/hide loading / error text boxes on each viewport.
var endLoadingHandler = cornerstoneTools.loadHandlerManager.getEndLoadHandler(); const endLoadingHandler = cornerstoneTools.loadHandlerManager.getEndLoadHandler();
var errorLoadingHandler = cornerstoneTools.loadHandlerManager.getErrorLoadingHandler(); const errorLoadingHandler = cornerstoneTools.loadHandlerManager.getErrorLoadingHandler();
// Get the current viewport settings // Get the current viewport settings
var viewport = cornerstone.getViewport(element); const viewport = cornerstone.getViewport(element);
const { studyInstanceUid, seriesInstanceUid, displaySetInstanceUid, currentImageIdIndex } = data;
// Store the current series data inside the Layout Manager // Store the current series data inside the Layout Manager
layoutManager.viewportData[viewportIndex] = { layoutManager.viewportData[viewportIndex] = {
imageId: imageId, imageId,
studyInstanceUid: data.studyInstanceUid, studyInstanceUid,
seriesInstanceUid: data.seriesInstanceUid, seriesInstanceUid,
displaySetInstanceUid: data.displaySetInstanceUid, displaySetInstanceUid,
currentImageIdIndex: data.currentImageIdIndex, currentImageIdIndex,
viewport: viewport, viewport,
viewportIndex: viewportIndex viewportIndex
}; };
// Start loading the image. // Start loading the image.
cornerstone.loadAndCacheImage(imageId).then(function(image) { cornerstone.loadAndCacheImage(imageId).then(image => {
var enabledElement; let enabledElement;
try { try {
enabledElement = cornerstone.getEnabledElement(element); enabledElement = cornerstone.getEnabledElement(element);
} catch (error) { }
catch (error) {
OHIF.log.warn('Viewport destroyed before loaded image could be displayed'); OHIF.log.warn('Viewport destroyed before loaded image could be displayed');
return; return;
} }
// Caches element's jQuery object
const jQueryEl = $(element);
// Update the enabled element with the image and viewport data // Update the enabled element with the image and viewport data
// This is not usually necessary, but we need them stored in case // This is not usually necessary, but we need them stored in case
// a sopClassUid-specific viewport setting is present. // a sopClassUid-specific viewport setting is present.
@ -154,8 +160,8 @@ function loadDisplaySetIntoViewport(data, templateData) {
return; return;
} }
var instance = displaySet.images[0]; const instance = displaySet.images[0];
var instanceClassViewport = getInstanceClassDefaultViewport(instance, enabledElement, image.imageId); const instanceClassViewport = getInstanceClassDefaultViewport(instance, enabledElement, image.imageId);
// If there are sopClassUid-specific viewport settings, apply them // If there are sopClassUid-specific viewport settings, apply them
if (instanceClassViewport) { if (instanceClassViewport) {
@ -167,7 +173,8 @@ function loadDisplaySetIntoViewport(data, templateData) {
// Resize the canvas to fit the current viewport element size. // Resize the canvas to fit the current viewport element size.
cornerstone.resize(element, false); cornerstone.resize(element, false);
} else if (data.viewport) { }
else if (data.viewport) {
// If there is a saved object containing Cornerstone viewport data // If there is a saved object containing Cornerstone viewport data
// (e.g. scale, invert, window settings) in the input data, apply it now. // (e.g. scale, invert, window settings) in the input data, apply it now.
cornerstone.displayImage(element, image, data.viewport); cornerstone.displayImage(element, image, data.viewport);
@ -175,7 +182,8 @@ function loadDisplaySetIntoViewport(data, templateData) {
// Resize the canvas to fit the current viewport element size. Fit the displayed // Resize the canvas to fit the current viewport element size. Fit the displayed
// image to the canvas dimensions. // image to the canvas dimensions.
cornerstone.resize(element, true); cornerstone.resize(element, true);
} else { }
else {
// If no saved viewport settings or modality-specific settings exists, // If no saved viewport settings or modality-specific settings exists,
// display the loaded image in the viewport element with no loaded viewport // display the loaded image in the viewport element with no loaded viewport
// settings. // settings.
@ -199,8 +207,8 @@ function loadDisplaySetIntoViewport(data, templateData) {
// Hide the viewport instructions (i.e. 'Drag a stack here') and show // Hide the viewport instructions (i.e. 'Drag a stack here') and show
// the viewport overlay data. // the viewport overlay data.
$(element).siblings('.viewportInstructions').hide(); jQueryEl.siblings('.viewportInstructions').hide();
$(element).siblings('.imageViewerViewportOverlay').show(); jQueryEl.siblings('.imageViewerViewportOverlay').show();
// Add stack state managers for the stack tool, CINE tool, and reference lines // Add stack state managers for the stack tool, CINE tool, and reference lines
cornerstoneTools.addStackStateManager(element, ['stack', 'playClip', 'referenceLines']); cornerstoneTools.addStackStateManager(element, ['stack', 'playClip', 'referenceLines']);
@ -213,16 +221,16 @@ function loadDisplaySetIntoViewport(data, templateData) {
cornerstoneTools.addToolState(element, 'stack', stack); cornerstoneTools.addToolState(element, 'stack', stack);
// Set the default CINE settings // Set the default CINE settings
var multiframeMetadata = instance.multiframeMetadata; const multiframeMetadata = instance.multiframeMetadata;
let fps; let fps;
if (multiframeMetadata) { if (multiframeMetadata && multiframeMetadata.averageFrameRate > 0) {
fps = multiframeMetadata.averageFrameRate fps = multiframeMetadata.averageFrameRate;
} else { } else {
fps = OHIF.viewer.cine.framesPerSecond fps = OHIF.viewer.cine.framesPerSecond;
} }
var cineToolData = { const cineToolData = {
loop: OHIF.viewer.cine.loop, loop: OHIF.viewer.cine.loop,
framesPerSecond: fps framesPerSecond: fps
}; };
@ -242,12 +250,12 @@ function loadDisplaySetIntoViewport(data, templateData) {
// Use the tool manager to enable the currently active tool for this // Use the tool manager to enable the currently active tool for this
// newly rendered element // newly rendered element
var activeTool = toolManager.getActiveTool(); const activeTool = toolManager.getActiveTool();
toolManager.setActiveTool(activeTool, [element]); toolManager.setActiveTool(activeTool, [element]);
// Define a function to run whenever the Cornerstone viewport is rendered // Define a function to run whenever the Cornerstone viewport is rendered
// (e.g. following a change of window or zoom) // (e.g. following a change of window or zoom)
function onImageRendered(e, eventData) { const onImageRendered = () => {
OHIF.log.info('imageViewerViewport onImageRendered'); OHIF.log.info('imageViewerViewport onImageRendered');
if (!layoutManager.viewportData[viewportIndex]) { if (!layoutManager.viewportData[viewportIndex]) {
@ -260,22 +268,22 @@ function loadDisplaySetIntoViewport(data, templateData) {
// Save the current viewport into the ViewerData global variable, as well as the // Save the current viewport into the ViewerData global variable, as well as the
// Meteor Session. This lets the viewport be saved/reloaded on a hot-code reload // Meteor Session. This lets the viewport be saved/reloaded on a hot-code reload
var viewport = cornerstone.getViewport(element); const viewport = cornerstone.getViewport(element);
layoutManager.viewportData[viewportIndex].viewport = viewport; layoutManager.viewportData[viewportIndex].viewport = viewport;
ViewerData[contentId].loadedSeriesData[viewportIndex].viewport = viewport; ViewerData[contentId].loadedSeriesData[viewportIndex].viewport = viewport;
Session.set('ViewerData', ViewerData); Session.set('ViewerData', ViewerData);
} };
// Attach the onImageRendered callback to the CornerstoneImageRendered event // Attach the onImageRendered callback to the CornerstoneImageRendered event
$(element).off('CornerstoneImageRendered', onImageRendered); jQueryEl.off('CornerstoneImageRendered', onImageRendered);
$(element).on('CornerstoneImageRendered', onImageRendered); jQueryEl.on('CornerstoneImageRendered', onImageRendered);
// Set a random value for the Session variable in order to trigger an overlay update // Set a random value for the Session variable in order to trigger an overlay update
Session.set('CornerstoneImageRendered' + viewportIndex, Random.id()); Session.set('CornerstoneImageRendered' + viewportIndex, Random.id());
// Define a function to run whenever the Cornerstone viewport changes images // Define a function to run whenever the Cornerstone viewport changes images
// (e.g. during scrolling) // (e.g. during scrolling)
function onNewImage(e, eventData) { const onNewImage = (e, eventData) => {
OHIF.log.info('imageViewerViewport onNewImage'); OHIF.log.info('imageViewerViewport onNewImage');
// Update the metaData for missing fields // Update the metaData for missing fields
@ -288,28 +296,26 @@ function loadDisplaySetIntoViewport(data, templateData) {
layoutManager.viewportData[viewportIndex].imageId = eventData.enabledElement.image.imageId; layoutManager.viewportData[viewportIndex].imageId = eventData.enabledElement.image.imageId;
// Get the element and stack data // Get the element and stack data
var element = e.target; const element = e.target;
var toolData = cornerstoneTools.getToolState(element, 'stack'); const toolData = cornerstoneTools.getToolState(element, 'stack');
if (!toolData || !toolData.data || !toolData.data.length) { if (!toolData || !toolData.data || !toolData.data.length) {
return; return;
} }
var stack = toolData.data[0];
// If this viewport is displaying a stack of images, save the current image // If this viewport is displaying a stack of images, save the current image
// index in the stack to the global ViewerData object, as well as the Meteor Session. // index in the stack to the global ViewerData object, as well as the Meteor Session.
var stack = cornerstoneTools.getToolState(element, 'stack'); const stack = cornerstoneTools.getToolState(element, 'stack');
if (stack && stack.data.length && stack.data[0].imageIds.length > 1) { if (stack && stack.data.length && stack.data[0].imageIds.length > 1) {
var imageIdIndex = stack.data[0].imageIds.indexOf(templateData.imageId); const imageIdIndex = stack.data[0].imageIds.indexOf(templateData.imageId);
layoutManager.viewportData[viewportIndex].currentImageIdIndex = imageIdIndex; layoutManager.viewportData[viewportIndex].currentImageIdIndex = imageIdIndex;
ViewerData[contentId].loadedSeriesData[viewportIndex].currentImageIdIndex = imageIdIndex; ViewerData[contentId].loadedSeriesData[viewportIndex].currentImageIdIndex = imageIdIndex;
Session.set('ViewerData', ViewerData); Session.set('ViewerData', ViewerData);
} }
} };
// Attach the onNewImage callback to the CornerstoneNewImage event // Attach the onNewImage callback to the CornerstoneNewImage event
$(element).off('CornerstoneNewImage', onNewImage); jQueryEl.off('CornerstoneNewImage', onNewImage);
$(element).on('CornerstoneNewImage', onNewImage); jQueryEl.on('CornerstoneNewImage', onNewImage);
// Set a random value for the Session variable in order to trigger an overlay update // Set a random value for the Session variable in order to trigger an overlay update
Session.set('CornerstoneNewImage' + viewportIndex, Random.id()); Session.set('CornerstoneNewImage' + viewportIndex, Random.id());
@ -317,13 +323,13 @@ function loadDisplaySetIntoViewport(data, templateData) {
// Define a function to trigger an event whenever a new viewport is being used // 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 // This is used to update the value of the "active viewport", when the user interacts
// with a new viewport element // with a new viewport element
function sendActivationTrigger(e, eventData) { const sendActivationTrigger = (e, eventData) => {
// Check if the current active viewport in the Meteor Session // Check if the current active viewport in the Meteor Session
// Is the same as the viewport in which the activation event was fired. // Is the same as the viewport in which the activation event was fired.
// If it was, no changes are necessary, so stop here. // If it was, no changes are necessary, so stop here.
var element = eventData.element; const element = eventData.element;
var activeViewportIndex = Session.get('activeViewport'); const activeViewportIndex = Session.get('activeViewport');
var viewportIndex = $('.imageViewerViewport').index(element); const viewportIndex = $('.imageViewerViewport').index(element);
// Reset the focus, even if we don't need to re-enable reference lines or prefetching // Reset the focus, even if we don't need to re-enable reference lines or prefetching
$(element).focus(); $(element).focus();
@ -337,21 +343,21 @@ function loadDisplaySetIntoViewport(data, templateData) {
// Otherwise, trigger an 'ActivateViewport' event to be handled by the Template event // Otherwise, trigger an 'ActivateViewport' event to be handled by the Template event
// handler // handler
eventData.viewportIndex = viewportIndex; eventData.viewportIndex = viewportIndex;
var customEvent = $.Event('ActivateViewport', eventData); const customEvent = $.Event('ActivateViewport', eventData);
// Need to overwrite the type set in the original event // Need to overwrite the type set in the original event
customEvent.type = 'ActivateViewport'; customEvent.type = 'ActivateViewport';
$(e.target).trigger(customEvent, eventData); $(e.target).trigger(customEvent, eventData);
} };
// Attach the sendActivationTrigger function to all of the Cornerstone interaction events // Attach the sendActivationTrigger function to all of the Cornerstone interaction events
$(element).off(allCornerstoneEvents, sendActivationTrigger); jQueryEl.off(allCornerstoneEvents, sendActivationTrigger);
$(element).on(allCornerstoneEvents, sendActivationTrigger); jQueryEl.on(allCornerstoneEvents, sendActivationTrigger);
ViewerData[contentId].loadedSeriesData = layoutManager.viewportData; ViewerData[contentId].loadedSeriesData = layoutManager.viewportData;
// Check if image plane (orientation / loction) data is present for the current image // Check if image plane (orientation / loction) data is present for the current image
var imagePlane = cornerstoneTools.metaData.get('imagePlane', image.imageId); const imagePlane = cornerstoneTools.metaData.get('imagePlane', image.imageId);
// If it is, and reference lines are enabled, add this element to the global synchronizer // If it is, and reference lines are enabled, add this element to the global synchronizer
// that is used for updating reference lines, and enable reference lines for this viewport. // that is used for updating reference lines, and enable reference lines for this viewport.