Lesion Tracker Redesign so far

This commit is contained in:
Erik Ziegler committed 2016-07-22 11:00:16 +02:00
1 parent b247e89d8b
commit a9a4f3f82b
109 files changed
+2972 -936

No files matched your search

-3
View File
@@ -1,9 +1,6 @@
body
background-color: black
.tab-content
height: calc(100% - 40px)
/* Mobile devices */
@media only screen and (min-device-width : 375px) and (max-device-width : 768px)
.logoContainer
-3
View File
@@ -34,7 +34,6 @@ Meteor.startup(function() {
touch: cornerstoneTools.exToolTouch
});
var states = toolManager.getToolDefaultStates();
states.deactivate.push('bidirectional');
states.deactivate.push('nonTarget');
@@ -44,7 +43,5 @@ Meteor.startup(function() {
states.deactivate.push('exTool');
states.activate.push('deleteLesionKeyboardTool');
states.enable.push('scaleOverlayTool');
toolManager.setToolDefaultStates(states);
});
@@ -1,18 +0,0 @@
<template name="viewer">
{{#if Template.subscriptionsReady}}
<div id="viewer">
{{>confirmDeleteDialog}}
{{>lesionLocationDialog}}
{{>nonTargetLesionDialog}}
{{>nonTargetResponseDialog}}
{{>conformanceCheckFeedback}}
{{>hidingPanel}}
<div id="viewportAndLesionTable">
{{>viewerMain }}
{{>lesionTable }}
</div>
</div>
{{else}}
{{>loadingText}}
{{/if}}
</template>
-302
View File
@@ -1,302 +0,0 @@
Session.setDefault('activeViewport', false);
Template.viewer.onCreated(function() {
// Attach the Window resize listener
$(window).on('resize', handleResize);
ValidationErrors.remove({});
var self = this;
var contentId = this.data.contentId;
OHIF = OHIF || {
viewer: {}
};
OHIF.viewer.loadIndicatorDelay = 3000;
OHIF.viewer.defaultTool = 'wwwc';
OHIF.viewer.refLinesEnabled = true;
OHIF.viewer.isPlaying = {};
OHIF.viewer.cine = {
framesPerSecond: 24,
loop: true
};
OHIF.viewer.functionList = {
invert: function(element) {
var viewport = cornerstone.getViewport(element);
viewport.invert = !viewport.invert;
cornerstone.setViewport(element, viewport);
},
resetViewport: function(element) {
cornerstone.reset(element);
},
playClip: function(element) {
var viewportIndex = $('.imageViewerViewport').index(element);
var isPlaying = OHIF.viewer.isPlaying[viewportIndex] || false;
if (isPlaying === true) {
cornerstoneTools.stopClip(element);
} else {
cornerstoneTools.playClip(element);
}
OHIF.viewer.isPlaying[viewportIndex] = !OHIF.viewer.isPlaying[viewportIndex];
Session.set('UpdateCINE', Random.id());
},
toggleLesionTrackerTools: toggleLesionTrackerTools,
clearTools: clearTools,
bidirectional: function() {
// Used for hotkeys
toolManager.setActiveTool('bidirectional');
},
nonTarget: function() {
// Used for hotkeys
toolManager.setActiveTool('nonTarget');
}
};
// The hotkey can also be an array (e.g. ["NUMPAD0", "0"])
OHIF.viewer.defaultHotkeys = OHIF.viewer.defaultHotkeys || {};
OHIF.viewer.defaultHotkeys.toggleLesionTrackerTools = 'O';
OHIF.viewer.defaultHotkeys.bidirectional = 'T'; // Target
OHIF.viewer.defaultHotkeys.nonTarget = 'N'; // Non-target
if (isTouchDevice()) {
OHIF.viewer.tooltipConfig = {
trigger: 'manual'
};
} else {
OHIF.viewer.tooltipConfig = {
trigger: 'hover'
};
}
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('CornerstoneNewImage', cornerstoneTools.updateImageSynchronizer);
if (ViewerData[contentId].loadedSeriesData) {
log.info('Reloading previous loadedSeriesData');
OHIF.viewer.loadedSeriesData = ViewerData[contentId].loadedSeriesData;
} else {
log.info('Setting default ViewerData');
OHIF.viewer.loadedSeriesData = {};
ViewerData[contentId].loadedSeriesData = OHIF.viewer.loadedSeriesData;
// Update the viewer data object
if (!this.data.timepointIds || this.data.timepointIds.length <= 1) {
// Update the viewer data object
ViewerData[contentId].viewportColumns = 1;
ViewerData[contentId].viewportRows = 1;
} else if (this.data.timepointIds.length > 1) {
ViewerData[contentId].viewportColumns = 2;
ViewerData[contentId].viewportRows = 1;
}
ViewerData[contentId].activeViewport = 0;
Session.set('ViewerData', ViewerData);
}
Session.set('activeViewport', ViewerData[contentId].activeViewport || false);
// Set lesion tool buttons as disabled if pixel spacing is not available for active element
self.autorun(pixelSpacingAutorunCheck);
// Update the ViewerStudies collection with the loaded studies
ViewerStudies.remove({});
this.data.studies.forEach(function(study) {
study.selected = true;
ViewerStudies.insert(study);
});
var patientId = this.data.studies[0].patientId;
Session.set('patientId', patientId);
self.autorun(function() {
var dataContext = Template.currentData();
self.subscribe('singlePatientAssociatedStudies', dataContext.studies[0].patientId);
self.subscribe('singlePatientTimepoints', dataContext.studies[0].patientId);
self.subscribe('singlePatientMeasurements', dataContext.studies[0].patientId);
self.subscribe('singlePatientImageMeasurements', dataContext.studies[0].patientId);
var subscriptionsReady = self.subscriptionsReady();
log.info('autorun viewer.js. Ready: ' + subscriptionsReady);
if (subscriptionsReady) {
// Set buttons as enabled/disabled when Timepoints collection is ready
timepointAutoCheck(dataContext);
TrialResponseCriteria.validateAllDelayed();
ViewerStudies.find().observe({
added: function(study) {
// Find the relevant timepoint given the newly added study
var timepoint = Timepoints.findOne({
studyInstanceUids: {
$in: [study.studyInstanceUid]
}
});
if (!timepoint) {
log.warn('Study added to Viewer has not been associated!');
return;
}
// Update the added document with its related timepointId
ViewerStudies.update(study._id, {
$set: {
timepointId: timepoint.timepointId
}
});
}
});
ImageMeasurements.find().observe({
added: function(data) {
if (data.clientId === ClientId) {
return;
}
syncImageMeasurementAndToolData(data);
// Update each displayed viewport
updateAllViewports();
},
changed: function(data) {
if (data.clientId === ClientId) {
return;
}
syncImageMeasurementAndToolData(data);
// Update each displayed viewport
updateAllViewports();
},
removed: function(data) {
if (data.clientId === ClientId) {
return;
}
removeToolDataWithMeasurementId(data.imageId, data.toolType, data.id);
// Update each displayed viewport
updateAllViewports();
}
});
Measurements.find().observe({
added: function(data) {
if (data.clientId === ClientId) {
TrialResponseCriteria.validateAllDelayed();
return;
}
log.info('Measurement added');
// This is used to re-add tools from the database into the
// Cornerstone ToolData structure
syncMeasurementAndToolData(data);
// Update each displayed viewport
updateAllViewports();
},
changed: function(data) {
if (data.clientId === ClientId) {
TrialResponseCriteria.validateAllDelayed();
return;
}
log.info('Measurement changed');
// This is used to update changed tools from the database
// in the Cornerstone ToolData structure
syncMeasurementAndToolData(data);
// Update each displayed viewport
updateAllViewports();
TrialResponseCriteria.validateAllDelayed();
},
removed: function(data) {
log.info('Measurement removed');
// Check that this Measurement actually contains timepoint data
if (!data || !data.timepoints) {
return;
}
// Get the Measurement ID and relevant tool so we can remove
// tool data for this Measurement
var measurementId = data._id;
var toolType = data.toolType;
// Remove the measurement from all the imageIds on which it exists
// as toolData
Object.keys(data.timepoints).forEach(function(timepointId) {
// Clear the toolData for this timepoint
var imageId = data.timepoints[timepointId].imageId;
removeToolDataWithMeasurementId(imageId, toolType, measurementId);
// Set reviewer for this timepoint
if (data.timepoints[timepointId].studyInstanceUid) {
Meteor.call('setReviewer',data.timepoints[timepointId].studyInstanceUid);
}
});
// Sync database data with toolData for all the measurements
// that have just been updated
// Note that here we need to use greater than and equals to
// find the Measurements, whereas on the server it's
// only "greater than", since inside this callback the
// Measurements have already been decremented.
var measurements = Measurements.find({
patientId: data.patientId,
lesionNumberAbsolute: {
$gte: data.lesionNumberAbsolute
}
});
measurements.forEach(function(measurement) {
syncMeasurementAndToolData(measurement);
});
// Update each displayed viewport
updateAllViewports();
ValidationErrors.remove({
measurementId: data._id
});
TrialResponseCriteria.validateAll();
}
});
}
});
});
Template.viewer.onRendered(function() {
// Enable hotkeys
enableHotkeys();
});
Template.viewer.onDestroyed(function() {
// Remove the Window resize listener
$(window).off('resize', handleResize);
OHIF.viewer.updateImageSynchronizer.destroy();
});
Template.viewer.events({
'CornerstoneToolsMeasurementAdded .imageViewerViewport': function(e, template, eventData) {
handleMeasurementAdded(e, eventData);
},
'CornerstoneToolsMeasurementModified .imageViewerViewport': function(e, template, eventData) {
handleMeasurementModified(e, eventData);
},
'CornerstoneToolsMeasurementRemoved .imageViewerViewport': function(e, template, eventData) {
handleMeasurementRemoved(e, eventData);
}
});
@@ -1,35 +0,0 @@
#viewer
width: 100%
height: 100%
margin: 0
padding: 0
background-color: black
#viewportAndLesionTable
height: 100%
width: 99%
background-color: black
float: right
-o-transition: all 0.3s ease-out;
-ms-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
#imageViewerViewports
.viewportContainer
&.active
border: 2px solid #777
&:hover, &:hover.active
border: 2px solid white
#btnCollapse
background-color: #333
border-color: black
&.active
border-color: #333
.btnCollapseIcon
color: white
@@ -1,7 +0,0 @@
<template name="viewerMain">
<div class="viewerMain">
{{ >toolbar toolbarOptions=toolbarOptions }}
<div id='layoutManagerTarget'>
</div>
</div>
</template>
@@ -1,127 +0,0 @@
Template.viewerMain.helpers({
toolbarOptions: function() {
var toolbarOptions = {};
var buttonData = [];
var btnGroup = [];
buttonData.push({
id: 'resetViewport',
title: 'Reset Viewport',
classes: 'imageViewerCommand',
iconClasses: 'fa fa-undo'
});
buttonData.push({
id: 'wwwc',
title: 'WW/WC',
classes: 'imageViewerTool',
iconClasses: 'fa fa-sun-o'
});
buttonData.push({
id: 'zoom',
title: 'Zoom',
classes: 'imageViewerTool',
iconClasses: 'fa fa-search'
});
buttonData.push({
id: 'pan',
title: 'Pan',
classes: 'imageViewerTool',
iconClasses: 'fa fa-arrows'
});
buttonData.push({
id: 'stackScroll',
title: 'Stack Scroll',
classes: 'imageViewerTool',
iconClasses: 'fa fa-bars'
});
buttonData.push({
id: 'length',
title: 'Length Measurement',
classes: 'imageViewerTool',
iconClasses: 'fa fa-arrows-v'
});
buttonData.push({
id: 'ellipticalRoi',
title: 'Elliptical ROI Measurement',
classes: 'imageViewerTool',
iconClasses: 'fa fa-circle-o'
});
buttonData.push({
id: 'bidirectional',
title: 'Target Tool',
classes: 'imageViewerTool',
iconClasses: 'fa fa-arrows-alt'
});
buttonData.push({
id: 'nonTarget',
title: 'Non-Target Tool',
classes: 'imageViewerTool',
iconClasses: 'fa fa-long-arrow-up'
});
buttonData.push({
id: 'clearTools',
title: 'Clear tools',
classes: 'imageViewerCommand',
iconClasses: 'fa fa-trash'
});
buttonData.push({
id: 'toggleLesionTrackerTools',
title: 'Show / hide tools',
classes: 'imageViewerCommand',
iconClasses: 'fa fa-eye'
});
// CR/UN/EX Tools
var crunexToolsBtns = {
id: 'crunexTools',
tools: [{
id: 'crTool',
title: 'CR Tool',
classes: 'imageViewerTool',
iconClasses: 'fa fa-cr'
}, {
id: 'unTool',
title: 'UN Tool',
classes: 'imageViewerTool',
iconClasses: 'fa fa-un'
}, {
id: 'exTool',
title: 'EX Tool',
classes: 'imageViewerTool',
iconClasses: 'fa fa-ex'
}],
title: 'CR/UN/EX',
groupIcon: 'fa fa-exchange'
};
btnGroup.push(crunexToolsBtns);
toolbarOptions.buttonData = buttonData;
toolbarOptions.includePlayClipButton = false;
toolbarOptions.includeLayoutButton = false;
toolbarOptions.includeHangingProtocolButtons = false;
toolbarOptions.btnGroup = btnGroup;
return toolbarOptions;
}
});
Template.viewerMain.onRendered(function() {
var parentNode = document.getElementById('layoutManagerTarget');
var studies = this.data.studies;
layoutManager = new LayoutManager(parentNode, studies);
ProtocolEngine = new HP.ProtocolEngine(layoutManager, studies);
HP.setEngine(ProtocolEngine);
});
@@ -1,23 +0,0 @@
.viewerMain
width: 100%
height: 84%
#layoutManagerTarget
width: 100%
height: calc(100% - 30px)
//font awesome icons
.fa-cr:before
content: 'CR'
font-weight: bold
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif
.fa-un:before
content: 'UN'
font-weight: bold
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif
.fa-ex:before
content: 'EX'
font-weight: bold
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif
+1 -2
View File
@@ -13,5 +13,4 @@
<meta name="MobileOptimized" content="320">
<meta name="HandheldFriendly" content="True">
<meta name="apple-mobile-web-app-capable" content="yes">
<link href='http://fonts.googleapis.com/css?family=Sanchez:400,700&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
</head>
</head>
+10 -8
View File
@@ -36,11 +36,11 @@ var routerOptions = {
Router.route('/', function() {
// Check user is logged in
if(Meteor.user() && Meteor.userId()) {
if (Meteor.user() && Meteor.userId()) {
if (verifyEmail && Meteor.user().emails && !Meteor.user().emails[0].verified) {
this.render('emailVerification', routerOptions);
} else {
this.render('worklist', routerOptions);
this.render('lesionTracker', routerOptions);
}
} else {
@@ -50,11 +50,11 @@ Router.route('/', function() {
Router.route('/worklist', function() {
// Check user is logged in
if(Meteor.user() && Meteor.userId()) {
if (Meteor.user() && Meteor.userId()) {
if (verifyEmail && Meteor.user().emails && !Meteor.user().emails[0].verified) {
this.render('emailVerification', routerOptions);
} else {
this.render('worklist', routerOptions);
this.render('lesionTracker', routerOptions);
}
} else {
@@ -77,15 +77,17 @@ Router.route('/viewer/timepoints/:_id', {
return;
}
this.render('worklist', routerOptions);
this.render('lesionTracker', routerOptions);
openNewTabWithTimepoint(timepointId);
}
});
Router.onBeforeAction(function () {
if (!Meteor.userId() && !Meteor.loggingIn()) {
Router.onBeforeAction(function() {
if (!Meteor.userId() && !Meteor.loggingIn()) {
this.render('entrySignIn');
} else {
this.next();
}
},{except: ['entrySignIn', 'entrySignUp', 'forgotPassword', 'resetPassword']});
}, {
except: ['entrySignIn', 'entrySignUp', 'forgotPassword', 'resetPassword']
});