LT-296: Clicking on measurement data in table activates the measurement

This commit is contained in:
Erik Ziegler 2016-11-12 17:52:12 +01:00
parent 42c938fb44
commit 80337f271e
19 changed files with 288 additions and 307 deletions

View File

@ -119,7 +119,9 @@ Template.viewer.onCreated(() => {
Template.viewer.helpers({
dataSourcesReady() {
// TODO: Find a better way to do this
return Session.get('TimepointsReady') && Session.get('MeasurementsReady');
const ready = Session.get('TimepointsReady') && Session.get('MeasurementsReady');
console.log('dataSourcesReady? : ' + ready);
return ready;
}
});

View File

@ -40,6 +40,7 @@ Template.caseProgress.onRendered(() => {
const api = instance.data.measurementApi;
const getNumMeasurementsAtTimepoint = timepointId => {
OHIF.log.info('getNumMeasurementsAtTimepoint');
const filter = {
timepointId: timepointId
};

View File

@ -1,3 +1,4 @@
import { OHIF } from 'meteor/ohif:core';
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
@ -48,28 +49,42 @@ Template.measurementTable.onRendered(() => {
});
Template.measurementTable.onRendered(() => {
// Find the first measurement by Lesion Number
let firstLesion; // = instance.data.measurementApi.firstLesion();
// Find and activate the first measurement by Lesion Number
// NOTE: This is inefficient, we should be using a hanging protocol
// to hang the first measurement's imageId immediately, rather
// than changing images after initial loading...
const instance = Template.instance();
// Create an object to store the ContentId inside
const templateData = {
contentId: Session.get('activeContentId')
const config = OHIF.measurements.MeasurementApi.getConfiguration();
const measurementTypeId = config.measurementTools[0].id;
const measurementApi = instance.data.measurementApi;
const collection = measurementApi[measurementTypeId];
const sorting = {
sort: {
measurementNumber: -1
}
};
// Activate the first lesion
if (firstLesion) {
OHIF.measurements.activateLesion(firstLesion._id, templateData);
}
});
const data = collection.find({}, sorting).fetch();
Template.measurementTable.events({
/**
* Retrieve the lesion id from the DOM data for this row
*/
/*'click table#tblLesion tbody tr': function(e, template) {
var measurementId = $(e.currentTarget).data('measurementid');
OHIF.measurements.activateLesion(measurementId, template.data);
},*/
const timepoints = instance.data.timepoints.get();
// TODO: Clean this up, it's probably an inefficient way to get what we need
const groupObject = _.groupBy(data, entry => entry.measurementNumber);
// Reformat the data
const rows = Object.keys(groupObject).map(key => ({
measurementTypeId: measurementTypeId,
measurementNumber: key,
entries: groupObject[key]
}));
const rowItem = rows[0];
// Activate the first lesion
if (rowItem) {
OHIF.measurements.jumpToRowItem(rowItem, timepoints);
}
});
Template.measurementTable.helpers({

View File

@ -46,19 +46,35 @@ Template.measurementTableHeaderRow.onCreated(() => {
Template.measurementTableHeaderRow.helpers({
numberOfMeasurements() {
return Template.instance().data.measurements.length;
const instance = Template.instance();
if (!instance.data.measurements) {
return;
}
return instance.data.measurements.length;
},
maxNumMeasurements() {
return Template.instance().maxNumMeasurements.get();
const instance = Template.instance();
if (!instance.data.measurements) {
return;
}
return instance.maxNumMeasurements.get();
},
anyUnmarkedLesionsLeft() {
// Skip New Lesions section
const instance = Template.instance();
const measurementType = instance.data.measurementType;
const measurementApi = instance.data.measurementApi;
const timepointApi = instance.data.timepointApi;
if (!instance.data.measurements) {
return;
}
const measurementType = instance.data.measurementType;
const config = OHIF.measurements.MeasurementApi.getConfiguration();
if (measurementType.id === config.newMeasurementTool.id) {
return;
}
const timepointApi = instance.data.timepointApi;
const current = instance.data.timepointApi.current();
const prior = instance.data.timepointApi.prior();
if (!prior) {
@ -69,6 +85,7 @@ Template.measurementTableHeaderRow.helpers({
const priorFilter = { timepointId: prior.timepointId };
const measurementTypeId = measurementType.id;
const measurementApi = instance.data.measurementApi;
const numCurrent = measurementApi.fetch(measurementTypeId, currentFilter).length;
const numPrior = measurementApi.fetch(measurementTypeId, priorFilter).length;
const remaining = Math.max(numPrior - numCurrent, 0);

View File

@ -1,10 +1,10 @@
<template name="measurementTableTimepointCell">
{{#if hasDataAtThisTimepoint}}
<div class="measurementTableTimepointCell" tabindex="1">
<div class="measurementTableTimepointCell noselect" tabindex="1">
{{displayData}}
</div>
{{else}}
<div class="measurementTableTimepointCell empty">
<div class="measurementTableTimepointCell noselect empty">
...
</div>
{{/if}}

View File

@ -59,39 +59,17 @@ const keys = {
};
Template.measurementTableTimepointCell.events({
'dblclick .measurementTableTimepointCell': function() {
OHIF.log.info('Double clicked on a timepoint cell');
// Search Measurements by lesion and timepoint
const currentMeasurement = Template.parentData(1).rowItem;
// Create some fake measurement data
const currentTimepointID = this.timepointId;
const timepointData = currentMeasurement.timepoints[currentTimepointID];
if (!timepointData) {
'click .measurementTableTimepointCell'(event, instance) {
if (!instance.data.timepointId) {
return;
}
let measurementData = {
id: currentMeasurement._id,
timepointId: currentTimepointID,
response: timepointData.response,
imageId: timepointData.imageId,
handles: timepointData.handles,
seriesInstanceUid: timepointData.seriesInstanceUid,
studyInstanceUid: timepointData.studyInstanceUid
};
if (currentMeasurement.isTarget) {
showConfirmDialog(function() {
OHIF.lesiontracker.clearMeasurementTimepointData(currentMeasurement._id, currentTimepointID);
});
} else {
changeNonTargetResponse(measurementData, null, doneCallback);
}
},
'keydown .measurementTableTimepointCell': function(e) {
const keyCode = e.which;
const rowItem = instance.data.rowItem;
const timepoints = instance.data.timepoints.get();
OHIF.measurements.jumpToRowItem(rowItem, timepoints);
}/*,
'keydown .measurementTableTimepointCell'(event, instance) {
const keyCode = event.which;
if (keyCode === keys.DELETE ||
(keyCode === keys.D && e.ctrlKey === true)) {
const currentMeasurement = Template.parentData(1).rowItem;
@ -101,5 +79,5 @@ Template.measurementTableTimepointCell.events({
OHIF.lesiontracker.clearMeasurementTimepointData(currentMeasurement._id, currentTimepointID);
});
}
}
}*/
});

View File

@ -1,6 +1,11 @@
@import "{design}/app"
.measurementTableTimepointCell
theme('border-left', '%s solid $uiBorderColor' % $uiBorderThickness)
theme('color', '$textPrimaryColor')
padding: 0 10px
theme('border-left', '%s solid $uiBorderColor' % $uiBorderThickness)
theme('color', '$textPrimaryColor')
padding: 0 10px
outline: none
cursor: pointer
&:hover
theme('color', '$activeColor')

View File

@ -21,7 +21,7 @@
{{#if config.newMeasurementTool}}
{{#let measurementType=(getNewMeasurementType config.newMeasurementTool)}}
{{#let newMeasure=(newMeasurements measurementType)}}
{{#if newMeasure}}
{{#if newMeasure.length}}
{{#let collection=newMeasure}}
{{>measurementTableHeaderRow
measurementType=measurementType

View File

@ -1,7 +1,7 @@
import { Template } from 'meteor/templating';
import { _ } from 'meteor/underscore';
const getLocation = collection => {
OHIF.measurements.getLocation = collection => {
for (let i = 0; i < collection.length; i++) {
if (collection[i].location) {
return collection[i].location;
@ -9,6 +9,8 @@ const getLocation = collection => {
}
};
const getLocation = OHIF.measurements.getLocation;
Template.measurementTableView.helpers({
getNewMeasurementType(tool) {
// TODO: Check Conformance criteria here.
@ -25,13 +27,13 @@ Template.measurementTableView.helpers({
const instance = Template.instance();
const measurementApi = instance.data.measurementApi;
const timepointApi = instance.data.timepointApi;
if (!measurementApi || !timepointApi) {
const baseline = timepointApi.baseline();
if (!measurementApi || !timepointApi || !baseline) {
return;
}
// Retrieve all the data for this Measurement type (e.g. 'targets')
// which was recorded at baseline.
const baseline = timepointApi.baseline();
const atBaseline = measurementApi.fetch(measurementTypeId, {
timepointId: baseline.timepointId
});
@ -65,14 +67,15 @@ Template.measurementTableView.helpers({
const instance = Template.instance();
const measurementApi = instance.data.measurementApi;
const timepointApi = instance.data.timepointApi;
const measurementTypeId = measurementType.measurementTypeId;
const current = instance.data.timepointApi.current();
const baseline = timepointApi.baseline();
if (!timepointApi) {
if (!measurementApi || !timepointApi || !current) {
return;
}
// If this is a baseline, stop here since there are no new measurements to display
const current = instance.data.timepointApi.current();
if (!current || current.timepointType === 'baseline') {
console.log('Skipping New Measurements section');
return;
@ -80,7 +83,7 @@ Template.measurementTableView.helpers({
// Retrieve all the data for this Measurement type (e.g. 'targets')
// which was recorded at baseline.
const baseline = timepointApi.baseline();
const measurementTypeId = measurementType.measurementTypeId;
const atBaseline = measurementApi.fetch(measurementTypeId, {
timepointId: baseline.timepointId
});

View File

@ -7,9 +7,8 @@
overflow-y: auto
margin-left: -6px
margin-right: -16px
padding-bottom: 100px
padding-bottom: 116px
padding-left: 6px
-webkit-overflow-scrolling: touch
&::-webkit-scrollbar

View File

@ -1,6 +1,5 @@
import { Meteor } from 'meteor/meteor';
import { $ } from 'meteor/jquery';
import { OHIF } from 'meteor/ohif:core';
class MeasurementHandlers {

View File

@ -1,118 +0,0 @@
import { $ } from 'meteor/jquery';
import { OHIF } from 'meteor/ohif:core';
/**
* Activates a set of lesions when lesion table row is clicked
*
* @param measurementId The unique key for a specific Measurement
*/
OHIF.measurements.activateLesion = (measurementId, templateData) => {
// Set background color of selected row
$(`tr[data-measurementid=${measurementId}]`).addClass('selectedRow')
.siblings().removeClass('selectedRow');
// Get the data for current measurement
const measurementData = Measurements.findOne(measurementId);
// If there is no measurement with this ID, stop here
if (!measurementData) {
OHIF.OHIF.log.warn('No Measurements entry associated to an ID in a lesion table row');
return;
}
// Create an empty array to store the ordered timepoint data for this measurement
const orderedTimepointEntries = [];
// Retrieve the Cursor for this patient's Timepoints in ascending order by studyDate
const sortedTimepoints = Timepoints.find({}, {
sort: {
latestDate: 1
}
});
// Loop through each timepoint and populate the orderTimepointEntries array with the
// measurement data at each timepoint. The most recent measurements will be first in the array.
sortedTimepoints.forEach(timepoint => {
const measurementDataAtTimepoint = measurementData.timepoints[timepoint.timepointId];
if (!measurementDataAtTimepoint) {
return;
}
orderedTimepointEntries.push(measurementDataAtTimepoint);
});
// If there is no timepoint data to display for this Measurement, stop here
if (!orderedTimepointEntries.length) {
return;
}
// Retrieve the list of available viewports
const $viewports = $('.imageViewerViewport').not('.empty');
// Remove earlier timepoint data entries
if (orderedTimepointEntries.length > $viewports.length) {
const difference = orderedTimepointEntries.length - $viewports.length;
orderedTimepointEntries.splice(0, difference);
}
// Loop through the viewports and display each timepoint
$viewports.each((viewportIndex, element) => {
// Stop if we run out of timepoints before viewports
if (viewportIndex >= orderedTimepointEntries.length) {
// Update the element anyway, to remove any other highlights that are present
OHIF.measurements.deactivateAllToolData(element, 'bidirectional');
OHIF.measurements.deactivateAllToolData(element, 'nonTarget');
OHIF.measurements.deactivateAllToolData(element, 'crTool');
OHIF.measurements.deactivateAllToolData(element, 'unTool');
OHIF.measurements.deactivateAllToolData(element, 'exTool');
return false;
}
// Find measurements related to the Nth timepoint
// TODO=Re-evaluate this approach to populating viewports with timepoints
// What is the desired behaviour here?
const measurementAtTimepoint = orderedTimepointEntries[viewportIndex];
// Find the image that is currently in this viewport
const enabledElement = cornerstone.getEnabledElement(element);
if (!enabledElement || !enabledElement.image) {
return;
}
// If there is no measurement data to display, stop here
if (!measurementAtTimepoint) {
// Update the element anyway, to remove any other highlights that are present
OHIF.measurements.deactivateAllToolData(element, 'bidirectional');
OHIF.measurements.deactivateAllToolData(element, 'nonTarget');
OHIF.measurements.deactivateAllToolData(element, 'crTool');
OHIF.measurements.deactivateAllToolData(element, 'unTool');
OHIF.measurements.deactivateAllToolData(element, 'exTool');
cornerstone.updateImage(element);
return;
}
// Check which study and series are required to display the measurement at this timepoint
const requiredSeriesData = {
seriesInstanceUid: measurementAtTimepoint.seriesInstanceUid,
studyInstanceUid: measurementAtTimepoint.studyInstanceUid
};
// Check if the study / series we need is already the one in the viewport
const currentSeriesData = OHIF.viewer.loadedSeriesData[viewportIndex];
const activateMeasurements = OHIF.measurements.activateMeasurements;
if (currentSeriesData.seriesInstanceUid === measurementAtTimepoint.seriesInstanceUid &&
currentSeriesData.studyInstanceUid === measurementAtTimepoint.studyInstanceUid) {
// If it is, activate the measurements in this viewport and stop here
activateMeasurements(element, measurementId, templateData, viewportIndex);
return;
}
// Otherwise, re-render the viewport with the required study/series, then
// add an onRendered callback to activate the measurements
window.layoutManager.rerenderViewportWithNewDisplaySet(element, requiredSeriesData, element => {
activateMeasurements(element, measurementId, templateData, viewportIndex);
});
});
};

View File

@ -1,51 +1,55 @@
import { OHIF } from 'meteor/ohif:core';
/**
* Activates a specific tool data instance and deactivates all other
* target and non-target measurement data
*
* @param element
* @param measurementData
*/
function activateTool(measurementData) {
const toolType = measurementData.toolType;
const imageId = measurementData.imageId;
const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState;
const toolData = toolState[imageId][toolType];
if (!toolData || !toolData.data || !toolData.data.length) {
return;
}
// When a measurement is selected, it will be activated in Cornerstone's
// tool data
const tool = toolData.data.find(data => data._id === measurementData._id);
tool.active = true;
};
/**
* Switch to the image of the correct image index
* Activate the selected measurement on the switched image (color to be green)
* Deactivate all other measurements on the switched image (color to be white)
*/
OHIF.measurements.activateMeasurements = (element, measurementId, templateData, viewportIndex) => {
// TODO=Switch this to use the new CornerstoneToolMeasurementModified event,
// Once it has 'modified on activation' set up
OHIF.measurements.activateMeasurements = (element, measurementData) => {
console.log('activateMeasurements');
// Activate the tool in the tool data
activateTool(measurementData);
const enabledElement = cornerstone.getEnabledElement(element);
const imageId = enabledElement.image.imageId;
const timepointData = OHIF.measurements.getTimepointObject(imageId);
const measurementData = Measurements.findOne(measurementId);
const currentImageId = enabledElement.image.imageId;
const toolData = cornerstoneTools.getToolState(element, 'stack');
const imageIdIndex = toolData.data[0].imageIds.indexOf(measurementData.imageId);
if (!timepointData) {
return;
// If we aren't currently displaying the image that this tool is on,
// scroll to it now.
if (currentImageId !== measurementData.imageId) {
cornerstoneTools.scrollToIndex(element, imageIdIndex);
}
const measurementAtTimepoint = measurementData.timepoints[timepointData.timepointId];
if (!measurementAtTimepoint) {
return;
}
// If type is active, load image and activate lesion
// If type is inactive, update lesions of enabledElement as inactive
//TODO: !stackData.currentImageIdIndex returns incorrect value
// Get loadedSeriesData currentImageIdIndex from ViewerData
const viewerData = window.ViewerData[templateData.contentId];
const loadedSeriesData = viewerData.loadedSeriesData[viewportIndex];
const elementCurrentImageIdIndex = loadedSeriesData.currentImageIdIndex;
const stackToolDataSource = cornerstoneTools.getToolState(element, 'stack');
const stackData = stackToolDataSource.data[0];
const imageIds = stackData.imageIds;
const imageIdIndex = imageIds.indexOf(measurementAtTimepoint.imageId);
if (imageIdIndex < 0) {
return;
}
if (imageIdIndex === elementCurrentImageIdIndex) {
OHIF.measurements.activateTool(element, measurementData, timepointData.timepointId);
} else {
cornerstone.loadAndCacheImage(measurementAtTimepoint.imageId).then(image => {
cornerstone.displayImage(element, image);
OHIF.measurements.activateTool(element, measurementData, timepointData.timepointId);
});
}
};
// TODO: Find another way to do this?
// This might update one element twice, but at least it makes sure all viewports are
// updated and the highlight is removed from inactive tools in all visible viewports
const $viewports = $('.imageViewerViewport');
$viewports.each((index, element) => {
cornerstone.updateImage(element)
});
};

View File

@ -1,44 +0,0 @@
import { OHIF } from 'meteor/ohif:core';
/**
* Activates a specific tool data instance and deactivates all other
* target and non-target measurement data
*
* @param element
* @param measurementData
* @param timepointId
*/
OHIF.measurements.activateTool = (element, measurementData, timepointId) => {
OHIF.measurements.deactivateAllToolData(element, 'bidirectional');
OHIF.measurements.deactivateAllToolData(element, 'nonTarget');
// Deactivate CRUNEX Tools
OHIF.measurements.deactivateAllToolData(element, 'crTool');
OHIF.measurements.deactivateAllToolData(element, 'unTool');
OHIF.measurements.deactivateAllToolData(element, 'exTool');
const toolType = measurementData.toolType;
const toolData = cornerstoneTools.getToolState(element, toolType);
if (!toolData) {
return;
}
const measurementAtTimepoint = measurementData.timepoints[timepointId];
for (let i = 0; i < toolData.data.length; i++) {
const data = toolData.data[i];
// When click a row of table measurements, measurement will be active and color will be green
// TODO= Remove this with the measurementId once it is in the tool data
if (data.seriesInstanceUid === measurementAtTimepoint.seriesInstanceUid &&
data.studyInstanceUid === measurementAtTimepoint.studyInstanceUid &&
data.lesionNumber === measurementData.lesionNumber &&
data.isTarget === measurementData.isTarget) {
data.active = true;
break;
}
}
cornerstone.updateImage(element);
};

View File

@ -3,17 +3,22 @@ import { OHIF } from 'meteor/ohif:core';
/**
* Sets all tool data entries value for 'active' to false
* This is used to remove the active color on entire sets of tools
*
* @param element The Cornerstone element that is being used
* @param toolType The tooltype of the tools that will be deactivated
*/
OHIF.measurements.deactivateAllToolData = (element, toolType) => {
const toolData = cornerstoneTools.getToolState(element, toolType);
if (!toolData) {
return;
}
OHIF.measurements.deactivateAllToolData = () => {
const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState;
for (let i = 0; i < toolData.data.length; i++) {
toolData.data[i].active = false;
}
Object.keys(toolState).forEach(imageId => {
const toolData = toolState[imageId];
Object.keys(toolData).forEach(toolType => {
const specificToolData = toolData[toolType];
if (!specificToolData || !specificToolData.data || !specificToolData.data.length) {
return;
}
specificToolData.data.forEach(data => {
data.active = false;
});
});
})
};

View File

@ -1,20 +0,0 @@
import { OHIF } from 'meteor/ohif:core';
/**
* Returns timepoint object given a specified imageId
*
* @param imageId
* @returns {*|{}} Timepoint object
*/
OHIF.measurements.getTimepointObject = imageId => {
const study = cornerstoneTools.metaData.get('study', imageId);
if (!study) {
return;
}
return Timepoints.findOne({
studyInstanceUids: {
$in: [study.studyInstanceUid]
}
});
};

View File

@ -1,9 +1,7 @@
import './activateLesion.js';
import './jumpToRowItem.js';
import './activateMeasurements.js';
import './activateTool.js';
import './deactivateAllToolData.js';
import './getTimepointName.js';
import './getTimepointObject.js';
import './hangingProtocolCustomizations.js';
import './MeasurementHandlers.js';
import './MeasurementManager.js';

View File

@ -0,0 +1,137 @@
import { $ } from 'meteor/jquery';
import { OHIF } from 'meteor/ohif:core';
function findAndRenderDisplaySet(displaySets, viewportIndex, studyInstanceUid, seriesInstanceUid, sopInstanceUid, renderedCallback) {
// Find the proper stack to display
const stacksFromSeries = displaySets.filter(stack => stack.seriesInstanceUid === seriesInstanceUid);
stack = stacksFromSeries.find(stack => {
const imageIndex = stack.images.findIndex(image => image.sopInstanceUid === sopInstanceUid);
return imageIndex > -1;
});
// TODO: make this work for multi-frame instances
const specificImageIndex = stack.images.findIndex(image => image.sopInstanceUid === sopInstanceUid);
const displaySetData = {
studyInstanceUid: studyInstanceUid,
seriesInstanceUid: seriesInstanceUid,
sopInstanceUid: sopInstanceUid,
displaySetInstanceUid: stack.displaySetInstanceUid,
currentImageIdIndex: specificImageIndex
};
// Add a renderedCallback to activate the measurements once it's
if (renderedCallback) {
displaySetData.renderedCallback = renderedCallback;
}
window.layoutManager.rerenderViewportWithNewDisplaySet(viewportIndex, displaySetData);
}
function renderIntoViewport(viewportIndex, studyInstanceUid, seriesInstanceUid, sopInstanceUid, renderedCallback) {
// First, check if we already have this study loaded
const alreadyLoadedStudy = ViewerStudies.findOne({studyInstanceUid});
if (alreadyLoadedStudy) {
// If the Study is already loaded, find the display set and render it
findAndRenderDisplaySet(alreadyLoadedStudy.displaySets, viewportIndex, studyInstanceUid, seriesInstanceUid, sopInstanceUid, renderedCallback)
} else {
// If not, retrieve the study metadata and then find the relevant display set and
// render it.
getStudyMetadata(study.studyInstanceUid, loadedStudy => {
loadedStudy.displaySets = createStacks(loadedStudy);
ViewerStudies.insert(loadedStudy);
findAndRenderDisplaySet(loadedStudy.displaySets, viewportIndex, studyInstanceUid, seriesInstanceUid, sopInstanceUid, renderedCallback)
});
}
}
function getDisplaySetData(instance, series, study) {
// First, check if we already have this study loaded
var alreadyLoaded = ViewerStudies.findOne({
studyInstanceUid: study.studyInstanceUid
});
// If not, retrieve it.
if (!alreadyLoaded) {
getStudyMetadata(priorStudy.studyInstanceUid, study => {
study.abstractPriorValue = abstractPriorValue;
study.displaySets = createStacks(study);
ViewerStudies.insert(study);
this.studies.push(study);
this.matchImages(viewport);
this.updateViewports();
});
}
return {};
}
/**
* Activates a set of lesions when lesion table row is clicked
*
* @param measurementId The unique key for a specific Measurement
*/
OHIF.measurements.jumpToRowItem = (rowItem, timepoints) => {
OHIF.measurements.deactivateAllToolData();
const activateMeasurements = OHIF.measurements.activateMeasurements;
console.log('jumpToRowItem');
// Retrieve the timepoints that are currently being displayed in the
// Measurement Table
const numTimepoints = timepoints.length;
// Retrieve the list of available viewports
const $viewports = $('.imageViewerViewport');
const numViewports = $viewports.length;
/*
Two Timepoints, Two measurements, load Followup (FU and BA), display FU in left and BA in right
Two Timepoints, One measurement (BA), on 2x1 view: Display BA in right
Two Timepoints, One measurement (FU), on 2x1 view: Display FU in left
Two Timepoints, Two measurements, load Baseline (FU and BA) on 1x1 view: Display whichever is clicked on?
One Timepoint, One measurement: Display clicked on in 1x1
*/
const numViewportsToUpdate = Math.min(numTimepoints, numViewports);
for (var i=0; i < numViewportsToUpdate; i++) {
const timepoint = timepoints[i];
const timepointId = timepoint.timepointId;
const dataAtThisTimepoint = _.where(rowItem.entries, {timepointId: timepointId});
if (!dataAtThisTimepoint || !dataAtThisTimepoint.length) {
continue;
}
const measurementData = dataAtThisTimepoint[0];
// Check if the study / series we need is already the one in the viewport
const element = $viewports.get(i);
const enabledElement = cornerstone.getEnabledElement(element)
const imageId = enabledElement.image.imageId;
const instance = cornerstoneTools.metaData.get('instance', imageId);
const series = cornerstoneTools.metaData.get('series', imageId);
const study = cornerstoneTools.metaData.get('study', imageId);
if (series.seriesInstanceUid === measurementData.seriesInstanceUid &&
study.studyInstanceUid === measurementData.studyInstanceUid) {
// If it is, activate the measurements in this viewport and stop here
activateMeasurements(element, measurementData);
} else {
// Otherwise, re-render the viewport with the required study/series, then
// add an onRendered callback to activate the measurements
const renderedCallback = element => {
activateMeasurements(element, measurementData);
};
// TODO: Support frames? e.g. for measurements on multi-frame instances
renderIntoViewport(i,
measurementData.studyInstanceUid,
measurementData.seriesInstanceUid,
measurementData.sopInstanceUid,
renderedCallback);
}
}
};

View File

@ -151,7 +151,7 @@ LayoutManager = class LayoutManager {
seriesInstanceUid: data.seriesInstanceUid,
studyInstanceUid: data.studyInstanceUid,
renderedCallback: data.renderedCallback,
currentImageIdIndex: 0
currentImageIdIndex: data.currentImageIdIndex || 0
};
// Remove the hover styling