PWV-3: Creating ohif:log package and partially refactoring ohif:measurements
This commit is contained in:
parent
f3f32518c6
commit
60aa1d0982
@ -95,6 +95,7 @@ ohif:cornerstone@0.0.1
|
||||
ohif:dicom-services@0.0.1
|
||||
ohif:hanging-protocols@0.0.1
|
||||
ohif:lesiontracker@0.0.1
|
||||
ohif:log@0.0.1
|
||||
ohif:measurements@0.0.1
|
||||
ohif:study-list@0.0.1
|
||||
ohif:user-management@0.0.1
|
||||
|
||||
@ -37,11 +37,11 @@ Template.viewer.onCreated(() => {
|
||||
OHIF.viewer.defaultHotkeys.nonTarget = 'N'; // Non-target
|
||||
|
||||
if (ViewerData[contentId].loadedSeriesData) {
|
||||
log.info('Reloading previous loadedSeriesData');
|
||||
OHIF.log.info('Reloading previous loadedSeriesData');
|
||||
OHIF.viewer.loadedSeriesData = ViewerData[contentId].loadedSeriesData;
|
||||
|
||||
} else {
|
||||
log.info('Setting default ViewerData');
|
||||
OHIF.log.info('Setting default ViewerData');
|
||||
OHIF.viewer.loadedSeriesData = {};
|
||||
ViewerData[contentId].loadedSeriesData = {};
|
||||
Session.set('ViewerData', ViewerData);
|
||||
|
||||
@ -33,10 +33,10 @@ Template.viewer.onCreated(() => {
|
||||
const contentId = instance.data.contentId;
|
||||
|
||||
if (ViewerData[contentId] && ViewerData[contentId].loadedSeriesData) {
|
||||
log.info('Reloading previous loadedSeriesData');
|
||||
OHIF.log.info('Reloading previous loadedSeriesData');
|
||||
OHIF.viewer.loadedSeriesData = ViewerData[contentId].loadedSeriesData;
|
||||
} else {
|
||||
log.info('Setting default ViewerData');
|
||||
OHIF.log.info('Setting default ViewerData');
|
||||
OHIF.viewer.loadedSeriesData = {};
|
||||
ViewerData[contentId] = {};
|
||||
ViewerData[contentId].loadedSeriesData = OHIF.viewer.loadedSeriesData;
|
||||
|
||||
@ -16,11 +16,11 @@ Template.viewer.onCreated(() => {
|
||||
const contentId = instance.data.contentId;
|
||||
|
||||
if (ViewerData[contentId].loadedSeriesData) {
|
||||
log.info('Reloading previous loadedSeriesData');
|
||||
OHIF.log.info('Reloading previous loadedSeriesData');
|
||||
OHIF.viewer.loadedSeriesData = ViewerData[contentId].loadedSeriesData;
|
||||
|
||||
} else {
|
||||
log.info('Setting default ViewerData');
|
||||
OHIF.log.info('Setting default ViewerData');
|
||||
OHIF.viewer.loadedSeriesData = {};
|
||||
ViewerData[contentId].loadedSeriesData = {};
|
||||
Session.set('ViewerData', ViewerData);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import './lib';
|
||||
import './components';
|
||||
import './helpers';
|
||||
import './components';
|
||||
import './ui';
|
||||
|
||||
import './routes.js';
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
const OHIF = {
|
||||
log: {},
|
||||
viewer: {},
|
||||
measurements: {}
|
||||
};
|
||||
|
||||
24
Packages/ohif-cornerstone/main.js
Normal file
24
Packages/ohif-cornerstone/main.js
Normal file
@ -0,0 +1,24 @@
|
||||
// TODO: stop exposing the libraries below and start using imports
|
||||
|
||||
import { cornerstone } from './client/cornerstone.js';
|
||||
import { dicomParser } from './client/dicomParser.js';
|
||||
import { cornerstoneMath } from './client/cornerstoneMath.js';
|
||||
import { cornerstoneTools } from './client/cornerstoneTools.js';
|
||||
import { cornerstoneWADOImageLoader } from './client/cornerstoneWADOImageLoader.js';
|
||||
|
||||
// Expose the cornerstone objects to the client if it is on development mode
|
||||
if (Meteor.isDevelopment) {
|
||||
window.cornerstone = cornerstone;
|
||||
window.cornerstoneMath = cornerstoneMath;
|
||||
window.cornerstoneTools = cornerstoneTools;
|
||||
window.cornerstoneWADOImageLoader = cornerstoneWADOImageLoader;
|
||||
window.dicomParser = dicomParser;
|
||||
}
|
||||
|
||||
export {
|
||||
cornerstone,
|
||||
cornerstoneMath,
|
||||
cornerstoneTools,
|
||||
cornerstoneWADOImageLoader,
|
||||
dicomParser
|
||||
};
|
||||
@ -41,5 +41,5 @@ Package.onUse(function(api) {
|
||||
api.export('cornerstoneMath', 'client');
|
||||
api.export('cornerstoneTools', 'client');
|
||||
api.export('cornerstoneWADOImageLoader', 'client');
|
||||
api.export('dicomParser', ['client', 'server']);
|
||||
});
|
||||
api.export('dicomParser', 'client');
|
||||
});
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
var keys = {
|
||||
ESC: 27
|
||||
};
|
||||
@ -118,7 +120,7 @@ function getActiveViewportImageId() {
|
||||
return;
|
||||
}
|
||||
} catch(error) {
|
||||
log.warn(error);
|
||||
OHIF.log.warn(error);
|
||||
return;
|
||||
}
|
||||
// Return the enabled element's imageId
|
||||
@ -141,7 +143,7 @@ function getAbstractPriorValue(imageId) {
|
||||
if (!priorStudy) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var studies = StudyListStudies.find({
|
||||
patientId: currentStudy.patientId,
|
||||
studyDate: {
|
||||
@ -184,7 +186,7 @@ function getCurrentAttributeValue(attribute, level) {
|
||||
if (level === 'protocol') {
|
||||
level = 'study';
|
||||
}
|
||||
|
||||
|
||||
if (attribute === 'abstractPriorValue') {
|
||||
return getAbstractPriorValue(imageId);
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
// Create package logger using loglevel
|
||||
// https://atmospherejs.com/spacejamio/loglevel
|
||||
log = loglevel.createPackageLogger('hangingprotocols', defaultLevel = 'info');
|
||||
@ -12,7 +12,6 @@ Package.onUse(function(api) {
|
||||
api.use('jquery');
|
||||
api.use('stylus');
|
||||
api.use('random');
|
||||
api.use('practicalmeteor:loglevel');
|
||||
api.use('templating');
|
||||
api.use('natestrauser:select2@4.0.1', 'client');
|
||||
api.use('clinical:router');
|
||||
@ -22,11 +21,6 @@ Package.onUse(function(api) {
|
||||
// Our custom packages
|
||||
api.use('ohif:viewerbase');
|
||||
|
||||
// This sets the default logging level of the package using the
|
||||
// loglevel package. It can be overridden in the JavaScript
|
||||
// console for debugging purposes
|
||||
api.addFiles('log.js');
|
||||
|
||||
api.addAssets('assets/dots.svg', 'client');
|
||||
|
||||
// Both client & server
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
TrialCriteriaTypes = new Meteor.Collection(null);
|
||||
|
||||
TrialCriteriaTypes.insert({
|
||||
@ -54,7 +56,7 @@ Template.optionsModal.events({
|
||||
'click a.clearAllStudyTimepointAssociations': function() {
|
||||
Meteor.call('clearAllTimepoints', function(error) {
|
||||
if (error) {
|
||||
log.warn(error);
|
||||
OHIF.log.warn(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
// Create a client-only Collection to store our Validation Errors
|
||||
ValidationErrors = new Meteor.Collection(null);
|
||||
ValidationErrors._debugName = 'ValidationErrors';
|
||||
@ -55,7 +57,7 @@ function addValidationErrorsToCollection(validationErrors, prefix, type) {
|
||||
* @returns {Array} Array of error messages related to the input conformance checks
|
||||
*/
|
||||
function assessGroupOfMeasurements(constraints) {
|
||||
log.info('assessGroupOfMeasurements');
|
||||
OHIF.log.info('assessGroupOfMeasurements');
|
||||
|
||||
// Retrieve the group-level constraints
|
||||
var groupConstraints = constraints.group;
|
||||
@ -95,7 +97,7 @@ function assessGroupOfMeasurements(constraints) {
|
||||
* @returns {Array} Array of error messages related to the input conformance checks
|
||||
*/
|
||||
function assessMeasurementPerOrgan(constraints) {
|
||||
log.info('assessMeasurementPerOrgan');
|
||||
OHIF.log.info('assessMeasurementPerOrgan');
|
||||
|
||||
// Retrieve the per-organ constraints
|
||||
var perOrganConstraints = constraints.perOrgan;
|
||||
@ -154,7 +156,7 @@ function assessMeasurementPerOrgan(constraints) {
|
||||
* @returns {Array} Array of error messages related to the input conformance checks
|
||||
*/
|
||||
function assessSingleMeasurement(constraints, measurementData) {
|
||||
log.info('assessSingleMeasurement');
|
||||
OHIF.log.info('assessSingleMeasurement');
|
||||
|
||||
// Check whether this is a Target or Non-Target Measurement
|
||||
var targetType = measurementData.isTarget ? 'target' : 'nonTarget';
|
||||
@ -262,7 +264,7 @@ function validateSingleMeasurement(measurementData) {
|
||||
}
|
||||
|
||||
function validateGroups() {
|
||||
log.info('validateGroups');
|
||||
OHIF.log.info('validateGroups');
|
||||
|
||||
// Obtain the names of the current TrialResponseAssessmentCriteria that
|
||||
// we are using.
|
||||
@ -281,7 +283,7 @@ function validateGroups() {
|
||||
// TODO: Revisit this! We can't use the Timepoints collection inside ANY
|
||||
// of these functions, since it causes an infinite loop, since Measurement
|
||||
// validation is performed inside the observe:added hook for the Measurements
|
||||
// Collection.
|
||||
// Collection.
|
||||
|
||||
var timepointTypes = ['baseline', 'followup'];
|
||||
timepointTypes.forEach(function(timepointType) {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
// Define the Trial Criteria Structure
|
||||
TrialCriteriaConstraints = {
|
||||
RECIST: RECIST,
|
||||
@ -148,7 +150,7 @@ function RECIST(image) {
|
||||
|
||||
/**
|
||||
* irRC Trial Criteria Definition
|
||||
*
|
||||
*
|
||||
* Baseline Checks:
|
||||
* - Target lesions must be >/= 10 X 10 mm
|
||||
* - Up to a max of 5 target lesions per organ
|
||||
@ -376,7 +378,7 @@ getTrialCriteriaConstraints = function(criteriaTypes, imageId) {
|
||||
|
||||
const timepoint = timepointApi.study(studyMetaData.studyInstanceUid)[0];
|
||||
if (!timepoint) {
|
||||
log.warn('Timepoint related to study is missing.');
|
||||
OHIF.log.warn('Timepoint related to study is missing.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
clearMeasurementTimepointData = function(measurementId, timepointId) {
|
||||
var data = Measurements.findOne(measurementId);
|
||||
|
||||
@ -16,7 +18,7 @@ clearMeasurementTimepointData = function(measurementId, timepointId) {
|
||||
};
|
||||
|
||||
function removeToolDataWithMeasurementId(imageId, toolType, measurementId) {
|
||||
log.info('removeToolDataWithMeasurementId');
|
||||
OHIF.log.info('removeToolDataWithMeasurementId');
|
||||
var toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState;
|
||||
|
||||
// Find any related toolData
|
||||
@ -39,8 +41,8 @@ function removeToolDataWithMeasurementId(imageId, toolType, measurementId) {
|
||||
}
|
||||
});
|
||||
|
||||
log.info('Removing Indices: ');
|
||||
log.info(toRemove);
|
||||
OHIF.log.info('Removing Indices: ');
|
||||
OHIF.log.info(toRemove);
|
||||
|
||||
// If any toolData entries need to be removed, splice them from
|
||||
// the toolData array
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
var responseTypes = {
|
||||
crTool: 'CR',
|
||||
exTool: 'EX',
|
||||
@ -16,7 +18,7 @@ convertNonTarget = function(measurementApi, measurementData, newTooltype) {
|
||||
});
|
||||
|
||||
if (timepoint && timepoint.timepointType !== 'followup') {
|
||||
log.warn('Not a followup');
|
||||
OHIF.log.warn('Not a followup');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Calculates a Timepoint's name based on how many timepoints exist between it
|
||||
* and the latest Baseline. Names returned are in the form of 'Baseline', or
|
||||
* 'Follow-up 1', 'Follow-up 2', and so on.
|
||||
*
|
||||
* @param timepoint
|
||||
* @returns {*} The timepoint name
|
||||
*/
|
||||
getTimepointName = function(timepoint) {
|
||||
// Check if this is a Baseline timepoint, if it is, return 'Baseline'
|
||||
if (timepoint.timepointType === 'baseline') {
|
||||
return 'Baseline';
|
||||
}
|
||||
|
||||
// Retrieve all of the relevant follow-up timepoints for this patient
|
||||
var followupTimepoints = Timepoints.find({
|
||||
patientId: timepoint.patientId,
|
||||
timepointType: timepoint.timepointType
|
||||
}, {
|
||||
sort: {
|
||||
latestDate: 1
|
||||
}
|
||||
});
|
||||
|
||||
// Create an array of just timepointIds, so we can use indexOf
|
||||
// on it to find the current timepoint's relative position
|
||||
var followupTimepointIds = followupTimepoints.map(function(timepoint) {
|
||||
return timepoint.timepointId;
|
||||
});
|
||||
|
||||
// Calculate the index of the current timepoint in the array of all
|
||||
// relevant follow-up timepoints
|
||||
var index = followupTimepointIds.indexOf(timepoint.timepointId) + 1;
|
||||
|
||||
// If index is 0, it means that the current timepoint was not in the list
|
||||
// Log a warning and return here
|
||||
if (!index) {
|
||||
log.warn('Current follow-up was not in the list of relevant follow-ups?');
|
||||
return;
|
||||
}
|
||||
|
||||
// Return the timepoint name as 'Follow-up N'
|
||||
return 'Follow-up ' + index;
|
||||
};
|
||||
@ -1,5 +1,7 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
pixelSpacingAutorunCheck = function() {
|
||||
log.info('lesionTool button change autorun');
|
||||
OHIF.log.info('lesionTool button change autorun');
|
||||
|
||||
// Get oncology tools
|
||||
var oncologyTools = $('button#lesion, button#nonTarget');
|
||||
@ -33,4 +35,4 @@ pixelSpacingAutorunCheck = function() {
|
||||
oncologyTools.prop('disabled', false);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Opens a new tab in the tabbed studylist environment using
|
||||
* a given timepoint and new tab title.
|
||||
@ -12,7 +14,7 @@ openNewTabWithTimepoint = function(timepointId, title) {
|
||||
const timepoint = Timepoints.findOne({
|
||||
timepointId: timepointId
|
||||
});
|
||||
|
||||
|
||||
if (!timepoint) {
|
||||
throw 'No such timepoint exists';
|
||||
}
|
||||
@ -73,7 +75,7 @@ function getDataFromTimepoint(timepoint) {
|
||||
relatedStudies = relatedStudies.concat(baseline.studyInstanceUids[0]);
|
||||
timepointIds.push(baseline.timepointId);
|
||||
} else {
|
||||
log.warn('No Baseline found while opening a Follow-up Timepoint');
|
||||
OHIF.log.warn('No Baseline found while opening a Follow-up Timepoint');
|
||||
}
|
||||
|
||||
timepointIds.push(timepoint.timepointId);
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
function toolDataExists(toolState, imageId, toolType) {
|
||||
const currentToolState = toolState[imageId][toolType];
|
||||
return (currentToolState && currentToolState.data && currentToolState.data.length);
|
||||
}
|
||||
|
||||
syncMeasurementAndToolData = function(measurement) {
|
||||
log.info('syncMeasurementAndToolData');
|
||||
OHIF.log.info('syncMeasurementAndToolData');
|
||||
|
||||
const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState;
|
||||
const imageId = measurement.imageId;
|
||||
@ -57,4 +59,4 @@ syncMeasurementAndToolData = function(measurement) {
|
||||
|
||||
// Add the MeasurementData into the toolData for this imageId
|
||||
toolState[imageId][toolType].data.push(measurement);
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
// Create package logger using loglevel
|
||||
// https://atmospherejs.com/spacejamio/loglevel
|
||||
log = loglevel.createPackageLogger('lesiontracker', defaultLevel = 'info');
|
||||
@ -15,9 +15,6 @@ Package.onUse(function(api) {
|
||||
|
||||
api.use('validatejs');
|
||||
|
||||
// Control over logging
|
||||
api.use('practicalmeteor:loglevel');
|
||||
|
||||
// Template overriding
|
||||
api.use('aldeed:template-extension@4.0.0');
|
||||
|
||||
@ -28,14 +25,12 @@ Package.onUse(function(api) {
|
||||
api.use('ohif:cornerstone');
|
||||
api.use('ohif:measurements');
|
||||
|
||||
api.addFiles('log.js', [ 'client', 'server' ]);
|
||||
|
||||
api.addFiles('both/configuration/bidirectional.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/nonTarget.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/ellipse.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/length.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/measurementTools.js', [ 'client', 'server' ]);
|
||||
|
||||
|
||||
api.addFiles('both/configuration/dataExchange.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/dataValidation.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/configuration.js', [ 'client', 'server' ]);
|
||||
@ -72,7 +67,7 @@ Package.onUse(function(api) {
|
||||
api.addFiles('client/components/measurementLocationDialog/measurementLocationDialog.html', 'client');
|
||||
api.addFiles('client/components/measurementLocationDialog/measurementLocationDialog.js', 'client');
|
||||
api.addFiles('client/components/measurementLocationDialog/measurementLocationDialog.styl', 'client');
|
||||
|
||||
|
||||
api.addFiles('client/components/nonTargetLesionDialog/nonTargetLesionDialog.html', 'client');
|
||||
api.addFiles('client/components/nonTargetLesionDialog/nonTargetLesionDialog.styl', 'client');
|
||||
api.addFiles('client/components/nonTargetLesionDialog/nonTargetLesionDialog.js', 'client');
|
||||
@ -92,7 +87,7 @@ Package.onUse(function(api) {
|
||||
// Library functions
|
||||
api.addFiles('lib/TrialCriteriaConstraints.js', 'client');
|
||||
api.addFiles('lib/MeasurementValidation.js', 'client');
|
||||
|
||||
|
||||
api.addFiles('lib/pixelSpacingAutorunCheck.js', 'client');
|
||||
api.addFiles('lib/toggleLesionTrackerTools.js', 'client');
|
||||
api.addFiles('lib/clearMeasurementTimepointData.js', 'client');
|
||||
@ -106,9 +101,6 @@ Package.onUse(function(api) {
|
||||
api.export('syncMeasurementAndToolData', 'client');
|
||||
api.export('syncImageMeasurementAndToolData', 'client');
|
||||
api.export('openNewTabWithTimepoint', 'client');
|
||||
api.export('activateLesion', 'client');
|
||||
api.export('activateMeasurements', 'client');
|
||||
api.export('deactivateAllToolData', 'client');
|
||||
api.export('toggleLesionTrackerTools', 'client');
|
||||
api.export('clearMeasurementTimepointData', 'client');
|
||||
api.export('getTrialCriteriaConstraints', 'client');
|
||||
|
||||
7
Packages/ohif-log/main.js
Normal file
7
Packages/ohif-log/main.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { loglevel } from 'meteor/practicalmeteor:loglevel';
|
||||
|
||||
const defaultLevel = Meteor.isProduction ? 'error' : 'trace';
|
||||
|
||||
// Create package logger using loglevel
|
||||
OHIF.log = loglevel.createLogger('', defaultLevel);
|
||||
20
Packages/ohif-log/package.js
Normal file
20
Packages/ohif-log/package.js
Normal file
@ -0,0 +1,20 @@
|
||||
Package.describe({
|
||||
name: 'ohif:log',
|
||||
summary: 'OHIF Logging',
|
||||
version: '0.0.1'
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
|
||||
api.use('ecmascript');
|
||||
api.use('standard-app-packages');
|
||||
|
||||
// Control over logging
|
||||
api.use('practicalmeteor:loglevel');
|
||||
|
||||
// Our custom packages
|
||||
api.use('ohif:core');
|
||||
|
||||
api.addFiles('main.js', [ 'client', 'server' ]);
|
||||
});
|
||||
@ -41,7 +41,6 @@ class MeasurementApi {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
retrievalFn().then(measurementData => {
|
||||
// TODO: implement converter here
|
||||
|
||||
console.log('Measurement data retrieval');
|
||||
console.log(measurementData);
|
||||
|
||||
@ -21,7 +21,7 @@ class TimepointApi {
|
||||
this.currentTimepointId = currentTimepointId;
|
||||
}
|
||||
|
||||
this.config = configuration || MeasurementApi.getConfiguration();
|
||||
this.config = configuration || OHIF.measurements.MeasurementApi.getConfiguration();
|
||||
}
|
||||
|
||||
retrieveTimepoints() {
|
||||
@ -38,7 +38,7 @@ class TimepointApi {
|
||||
retrievalFn().then(timepointData => {
|
||||
console.log('Timepoint data retrieval');
|
||||
console.log(timepointData);
|
||||
timepointData.forEach(timepoint => {
|
||||
_.each(timepointData, timepoint => {
|
||||
delete timepoint._id;
|
||||
this.timepoints.insert(timepoint);
|
||||
});
|
||||
@ -191,7 +191,7 @@ class TimepointApi {
|
||||
// If index is 0, it means that the current timepoint was not in the list
|
||||
// Log a warning and return here
|
||||
if (!index) {
|
||||
log.warn('Current follow-up was not in the list of relevant follow-ups?');
|
||||
OHIF.log.warn('Current follow-up was not in the list of relevant follow-ups?');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.associationModal.events({
|
||||
'click #saveAssociations': function(e) {
|
||||
log.info('Saving associations');
|
||||
OHIF.log.info('Saving associations');
|
||||
const Timepoints = StudyList.timepointApi.timepoints;
|
||||
|
||||
// Close the modal
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
// Use Aldeed's meteor-template-extension package to replace the
|
||||
// default StudyListStudy template.
|
||||
// See https://github.com/aldeed/meteor-template-extension
|
||||
@ -68,7 +70,7 @@ function removeTimepointAssociations() {
|
||||
// from the Timepoints Collection via a server call
|
||||
Meteor.call('removeTimepoint', timepoint._id, function(error) {
|
||||
if (error) {
|
||||
log.warn(error);
|
||||
OHIF.log.warn(error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ Template.measurementTable.onRendered(() => {
|
||||
|
||||
// Activate the first lesion
|
||||
if (firstLesion) {
|
||||
activateLesion(firstLesion._id, templateData);
|
||||
OHIF.measurements.activateLesion(firstLesion._id, templateData);
|
||||
}
|
||||
});
|
||||
|
||||
@ -67,7 +67,7 @@ Template.measurementTable.events({
|
||||
*/
|
||||
/*'click table#tblLesion tbody tr': function(e, template) {
|
||||
var measurementId = $(e.currentTarget).data('measurementid');
|
||||
activateLesion(measurementId, template.data);
|
||||
OHIF.measurements.activateLesion(measurementId, template.data);
|
||||
},*/
|
||||
});
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
function doneCallback(measurementData, deleteTool) {
|
||||
// If a Lesion or Non-Target is removed via a dialog
|
||||
// opened by the Lesion Table, we should clear the data for
|
||||
@ -5,7 +7,7 @@ function doneCallback(measurementData, deleteTool) {
|
||||
if (deleteTool === true) {
|
||||
Meteor.call('removeMeasurement', measurementData.id, function(error, response) {
|
||||
if (error) {
|
||||
log.warn(error);
|
||||
OHIF.log.warn(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -25,7 +27,7 @@ Template.measurementTableRow.events({
|
||||
},
|
||||
|
||||
'dblclick .location': function() {
|
||||
log.info('Double clicked on Lesion Location cell');
|
||||
OHIF.log.info('Double clicked on Lesion Location cell');
|
||||
|
||||
var measurementData = this;
|
||||
|
||||
@ -50,7 +52,7 @@ Template.measurementTableRow.events({
|
||||
showConfirmDialog(() => {
|
||||
Meteor.call('removeMeasurement', currentMeasurement._id, (error, response) => {
|
||||
if (error) {
|
||||
log.warn(error);
|
||||
OHIF.log.warn(error);
|
||||
}
|
||||
});
|
||||
}, options);
|
||||
|
||||
@ -43,7 +43,7 @@ function doneCallback(measurementData, deleteTool) {
|
||||
// opened by the Lesion Table, we should clear the data for
|
||||
// the specified Timepoint Cell
|
||||
if (deleteTool === true) {
|
||||
log.info('Confirm clicked!');
|
||||
OHIF.log.info('Confirm clicked!');
|
||||
clearMeasurementTimepointData(measurementData.id, measurementData.timepointId);
|
||||
}
|
||||
}
|
||||
@ -56,7 +56,7 @@ const keys = {
|
||||
|
||||
Template.measurementTableTimepointCell.events({
|
||||
'dblclick .measurementTableTimepointCell': function() {
|
||||
log.info('Double clicked on a timepoint cell');
|
||||
OHIF.log.info('Double clicked on a timepoint cell');
|
||||
// Search Measurements by lesion and timepoint
|
||||
const currentMeasurement = Template.parentData(1).rowItem;
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<template name="measurementTableView">
|
||||
<div class="measurementTableView scrollArea">
|
||||
{{ #let config=measurementConfiguration}}
|
||||
{{ #each measurementType in config.measurementTools}}
|
||||
{{#if measurementType.options.showInMeasurementTable }}
|
||||
{{#let config=measurementConfiguration}}
|
||||
{{#each measurementType in config.measurementTools}}
|
||||
{{#if measurementType.options.showInMeasurementTable}}
|
||||
{{#let collection=(groupByMeasurementNumber measurementType.id)}}
|
||||
{{>measurementTableHeaderRow
|
||||
measurementType=measurementType
|
||||
@ -16,11 +16,11 @@
|
||||
{{/each}}
|
||||
{{/let}}
|
||||
{{/if}}
|
||||
{{ /each }}
|
||||
{{/each}}
|
||||
|
||||
{{#if config.newMeasurementTool }}
|
||||
{{ #let new=newMeasurements }}
|
||||
{{#if new }}
|
||||
{{#if config.newMeasurementTool}}
|
||||
{{#let new=newMeasurements}}
|
||||
{{#if new}}
|
||||
{{#let collection=new tool=config.newMeasurementTool}}
|
||||
{{>measurementTableHeaderRow
|
||||
measurementType=tool.measurementType
|
||||
|
||||
1
Packages/ohif-measurements/client/helpers/index.js
Normal file
1
Packages/ohif-measurements/client/helpers/index.js
Normal file
@ -0,0 +1 @@
|
||||
import './measurements.js';
|
||||
@ -1,21 +1,7 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
// Get the current measurement API configuration with information about tools, data exchange
|
||||
// and data validation.
|
||||
Template.registerHelper('measurementConfiguration', () => {
|
||||
//console.log('helper:measurementTools');
|
||||
if (!OHIF.measurements.MeasurementApi) {
|
||||
return;
|
||||
}
|
||||
|
||||
const config = OHIF.measurements.MeasurementApi.getConfiguration();
|
||||
return config;
|
||||
});
|
||||
|
||||
Template.registerHelper('measurementApiCollection', measurementTypeId => {
|
||||
//console.log('helper:measurementApiCollection');
|
||||
if (!measurementTypeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const api = Template.instance().data.measurementApi;
|
||||
return api[measurementTypeId].find();
|
||||
return OHIF.measurements.MeasurementApi.getConfiguration();
|
||||
});
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
Template.registerHelper('getTimepointName', timepoint => {
|
||||
const instance = Template.instance()
|
||||
const timepointApi = instance.data.timepointApi;
|
||||
return timepointApi.name(timepoint);
|
||||
});
|
||||
4
Packages/ohif-measurements/client/index.js
Normal file
4
Packages/ohif-measurements/client/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
import './lib';
|
||||
import './helpers';
|
||||
// import './components';
|
||||
// import './ui';
|
||||
@ -38,7 +38,7 @@ MeasurementHandlers.onAdded = (e, instance, eventData) => {
|
||||
const sopInstanceUid = sopInstance.sopInstanceUid;
|
||||
const frameIndex = sopInstance.frame || 0;
|
||||
|
||||
log.info('CornerstoneToolsMeasurementAdded');
|
||||
OHIF.log.info('CornerstoneToolsMeasurementAdded');
|
||||
|
||||
let measurement = $.extend({
|
||||
userId: Meteor.userId(),
|
||||
@ -108,7 +108,7 @@ MeasurementHandlers.onModified = (e, instance, eventData) => {
|
||||
const sopInstanceUid = sopInstance.sopInstanceUid;
|
||||
const frameIndex = sopInstance.frame || 0;
|
||||
|
||||
log.info('CornerstoneToolsMeasurementModified');
|
||||
OHIF.log.info('CornerstoneToolsMeasurementModified');
|
||||
|
||||
let measurement = Collection.findOne(measurementData.id);
|
||||
|
||||
@ -141,7 +141,7 @@ MeasurementHandlers.onRemoved = (e, instance, eventData) => {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info('CornerstoneToolsMeasurementRemoved');
|
||||
OHIF.log.info('CornerstoneToolsMeasurementRemoved');
|
||||
|
||||
const measurementToolConfiguration = config.measurementTools[index];
|
||||
const measurementApi = instance.data.measurementApi;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { $ } from 'meteor/jquery';
|
||||
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
@ -5,35 +7,34 @@ import { OHIF } from 'meteor/ohif:core';
|
||||
*
|
||||
* @param measurementId The unique key for a specific Measurement
|
||||
*/
|
||||
activateLesion = function(measurementId, templateData) {
|
||||
|
||||
OHIF.measurements.activateLesion = (measurementId, templateData) => {
|
||||
// Set background color of selected row
|
||||
$('tr[data-measurementid=' + measurementId + ']').addClass('selectedRow').siblings().removeClass('selectedRow');
|
||||
$(`tr[data-measurementid=${measurementId}]`).addClass('selectedRow')
|
||||
.siblings().removeClass('selectedRow');
|
||||
|
||||
var measurementData = Measurements.findOne(measurementId);
|
||||
// Get the data for current measurement
|
||||
const measurementData = Measurements.findOne(measurementId);
|
||||
|
||||
// If there is no measurement with this ID, stop here
|
||||
if (!measurementData) {
|
||||
log.warn('No Measurements entry associated to an ID in a lesion table row');
|
||||
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
|
||||
var orderedTimepointEntries = [];
|
||||
// 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
|
||||
var sortedTimepoints = Timepoints.find({}, {
|
||||
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(function(timepoint) {
|
||||
var measurementDataAtTimepoint = measurementData.timepoints[timepoint.timepointId];
|
||||
// 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;
|
||||
}
|
||||
@ -47,24 +48,24 @@ activateLesion = function(measurementId, templateData) {
|
||||
}
|
||||
|
||||
// Retrieve the list of available viewports
|
||||
var viewports = $('.imageViewerViewport').not('.empty');
|
||||
const $viewports = $('.imageViewerViewport').not('.empty');
|
||||
|
||||
// Remove earlier timepoint data entries
|
||||
if (orderedTimepointEntries.length > viewports.length) {
|
||||
var difference = orderedTimepointEntries.length - viewports.length;
|
||||
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(function(viewportIndex, element) {
|
||||
$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
|
||||
deactivateAllToolData(element, 'bidirectional');
|
||||
deactivateAllToolData(element, 'nonTarget');
|
||||
deactivateAllToolData(element, 'crTool');
|
||||
deactivateAllToolData(element, 'unTool');
|
||||
deactivateAllToolData(element, 'exTool');
|
||||
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;
|
||||
}
|
||||
@ -72,7 +73,7 @@ activateLesion = function(measurementId, templateData) {
|
||||
// Find measurements related to the Nth timepoint
|
||||
// TODO=Re-evaluate this approach to populating viewports with timepoints
|
||||
// What is the desired behaviour here?
|
||||
var measurementAtTimepoint = orderedTimepointEntries[viewportIndex];
|
||||
const measurementAtTimepoint = orderedTimepointEntries[viewportIndex];
|
||||
|
||||
// Find the image that is currently in this viewport
|
||||
var enabledElement = cornerstone.getEnabledElement(element);
|
||||
@ -83,23 +84,24 @@ activateLesion = function(measurementId, templateData) {
|
||||
// If there is no measurement data to display, stop here
|
||||
if (!measurementAtTimepoint) {
|
||||
// Update the element anyway, to remove any other highlights that are present
|
||||
deactivateAllToolData(element, 'bidirectional');
|
||||
deactivateAllToolData(element, 'nonTarget');
|
||||
deactivateAllToolData(element, 'crTool');
|
||||
deactivateAllToolData(element, 'unTool');
|
||||
deactivateAllToolData(element, 'exTool');
|
||||
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
|
||||
var requiredSeriesData = {
|
||||
const requiredSeriesData = {
|
||||
seriesInstanceUid: measurementAtTimepoint.seriesInstanceUid,
|
||||
studyInstanceUid: measurementAtTimepoint.studyInstanceUid
|
||||
};
|
||||
|
||||
// Check if the study / series we need is already the one in the viewport
|
||||
var currentSeriesData = OHIF.viewer.loadedSeriesData[viewportIndex];
|
||||
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
|
||||
@ -109,7 +111,7 @@ activateLesion = function(measurementId, templateData) {
|
||||
|
||||
// Otherwise, re-render the viewport with the required study/series, then
|
||||
// add an onRendered callback to activate the measurements
|
||||
layoutManager.rerenderViewportWithNewDisplaySet(element, requiredSeriesData, function(element) {
|
||||
layoutManager.rerenderViewportWithNewDisplaySet(element, requiredSeriesData, element => {
|
||||
activateMeasurements(element, measurementId, templateData, viewportIndex);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,22 +1,24 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
activateMeasurements = function(element, measurementId, templateData, viewportIndex) {
|
||||
OHIF.measurements.activateMeasurements = (element, measurementId, templateData, viewportIndex) => {
|
||||
// TODO=Switch this to use the new CornerstoneToolMeasurementModified event,
|
||||
// Once it has 'modified on activation' set up
|
||||
|
||||
var enabledElement = cornerstone.getEnabledElement(element);
|
||||
var imageId = enabledElement.image.imageId;
|
||||
var timepointData = getTimepointObject(imageId);
|
||||
var measurementData = Measurements.findOne(measurementId);
|
||||
const enabledElement = cornerstone.getEnabledElement(element);
|
||||
const imageId = enabledElement.image.imageId;
|
||||
const timepointData = getTimepointObject(imageId);
|
||||
const measurementData = Measurements.findOne(measurementId);
|
||||
|
||||
if (!timepointData) {
|
||||
return;
|
||||
}
|
||||
|
||||
var measurementAtTimepoint = measurementData.timepoints[timepointData.timepointId];
|
||||
const measurementAtTimepoint = measurementData.timepoints[timepointData.timepointId];
|
||||
if (!measurementAtTimepoint) {
|
||||
return;
|
||||
}
|
||||
@ -25,68 +27,25 @@ activateMeasurements = function(element, measurementId, templateData, viewportIn
|
||||
// If type is inactive, update lesions of enabledElement as inactive
|
||||
//TODO: !stackData.currentImageIdIndex returns incorrect value
|
||||
// Get loadedSeriesData currentImageIdIndex from ViewerData
|
||||
var contentId = templateData.contentId;
|
||||
var viewerData = ViewerData[contentId];
|
||||
var elementCurrentImageIdIndex = viewerData.loadedSeriesData[viewportIndex].currentImageIdIndex;
|
||||
const viewerData = ViewerData[templateData.contentId];
|
||||
const loadedSeriesData = viewerData.loadedSeriesData[viewportIndex];
|
||||
const elementCurrentImageIdIndex = loadedSeriesData.currentImageIdIndex;
|
||||
|
||||
var stackToolDataSource = cornerstoneTools.getToolState(element, 'stack');
|
||||
var stackData = stackToolDataSource.data[0];
|
||||
var imageIds = stackData.imageIds;
|
||||
var imageIdIndex = imageIds.indexOf(measurementAtTimepoint.imageId);
|
||||
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) {
|
||||
activateTool(element, measurementData, timepointData.timepointId);
|
||||
OHIF.measurements.activateTool(element, measurementData, timepointData.timepointId);
|
||||
} else {
|
||||
cornerstone.loadAndCacheImage(imageIds[imageIdIndex]).then(function(image) {
|
||||
cornerstone.loadAndCacheImage(measurementAtTimepoint.imageId).then(image => {
|
||||
cornerstone.displayImage(element, image);
|
||||
activateTool(element, measurementData, timepointData.timepointId);
|
||||
OHIF.measurements.activateTool(element, measurementData, timepointData.timepointId);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Activates a specific tool data instance and deactivates all other
|
||||
* target and non-target measurement data
|
||||
*
|
||||
* @param element
|
||||
* @param measurementData
|
||||
* @param timepointId
|
||||
*/
|
||||
function activateTool(element, measurementData, timepointId) {
|
||||
deactivateAllToolData(element, 'bidirectional');
|
||||
deactivateAllToolData(element, 'nonTarget');
|
||||
|
||||
// Deactivate CRUNEX Tools
|
||||
deactivateAllToolData(element, 'crTool');
|
||||
deactivateAllToolData(element, 'unTool');
|
||||
deactivateAllToolData(element, 'exTool');
|
||||
|
||||
var toolType = measurementData.toolType;
|
||||
var toolData = cornerstoneTools.getToolState(element, toolType);
|
||||
if (!toolData) {
|
||||
return;
|
||||
}
|
||||
|
||||
var measurementAtTimepoint = measurementData.timepoints[timepointId];
|
||||
|
||||
for (var i = 0; i < toolData.data.length; i++) {
|
||||
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);
|
||||
}
|
||||
|
||||
44
Packages/ohif-measurements/client/lib/activateTool.js
Normal file
44
Packages/ohif-measurements/client/lib/activateTool.js
Normal file
@ -0,0 +1,44 @@
|
||||
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');
|
||||
|
||||
var toolType = measurementData.toolType;
|
||||
var toolData = cornerstoneTools.getToolState(element, toolType);
|
||||
if (!toolData) {
|
||||
return;
|
||||
}
|
||||
|
||||
var measurementAtTimepoint = measurementData.timepoints[timepointId];
|
||||
|
||||
for (var i = 0; i < toolData.data.length; i++) {
|
||||
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);
|
||||
};
|
||||
@ -1,60 +0,0 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
export const clearTools = () => {
|
||||
const config = OHIF.measurements.MeasurementApi.getConfiguration();
|
||||
const toolTypes = config.measurementTools.map(tool => {
|
||||
return tool.cornerstoneToolType;
|
||||
});
|
||||
|
||||
const $viewportElements = $('.imageViewerViewport').not('.empty');
|
||||
|
||||
let seriesInstanceUids = []; // Holds seriesInstanceUid of imageViewerViewport elements
|
||||
$viewportElements.each((index, element) => {
|
||||
const enabledElement = cornerstone.getEnabledElement(element);
|
||||
const study = cornerstoneTools.metaData.get('study', enabledElement.image.imageId);
|
||||
if (!study) {
|
||||
return;
|
||||
}
|
||||
|
||||
const series = cornerstoneTools.metaData.get('series', enabledElement.image.imageId);
|
||||
if (!series) {
|
||||
return;
|
||||
}
|
||||
|
||||
seriesInstanceUids.push(series.seriesInstanceUid);
|
||||
});
|
||||
|
||||
// Set null array for toolState data found by imageId and toolType
|
||||
const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState;
|
||||
const toolStateKeys = Object.keys(toolState).slice(0);
|
||||
toolStateKeys.forEach(imageId => {
|
||||
toolTypes.forEach(toolType => {
|
||||
const toolTypeData = toolState[imageId][toolType];
|
||||
if (!toolTypeData || !toolTypeData.data.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const series = cornerstoneTools.metaData.get('series', imageId);
|
||||
if (!series) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (seriesInstanceUids.indexOf(series.seriesInstanceUid) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If seriesInstanceUid is found in seriesInstanceUids, set toolState data as null
|
||||
toolState[imageId][toolType] = {
|
||||
data: []
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
// Update imageViewerViewport elements to remove lesions on current image
|
||||
$viewportElements.each((index, element) => {
|
||||
cornerstone.updateImage(element);
|
||||
});
|
||||
|
||||
// Clear all validation errors
|
||||
ValidationErrors.remove({});
|
||||
};
|
||||
@ -1,3 +1,5 @@
|
||||
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
|
||||
@ -5,7 +7,7 @@
|
||||
* @param element The Cornerstone element that is being used
|
||||
* @param toolType The tooltype of the tools that will be deactivated
|
||||
*/
|
||||
deactivateAllToolData = function(element, toolType) {
|
||||
OHIF.measurements.deactivateAllToolData = (element, toolType) => {
|
||||
var toolData = cornerstoneTools.getToolState(element, toolType);
|
||||
if (!toolData) {
|
||||
return;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Calculates a Timepoint's name based on how many timepoints exist between it
|
||||
* and the latest Baseline. Names returned are in the form of 'Baseline', or
|
||||
@ -6,7 +8,7 @@
|
||||
* @param timepoint
|
||||
* @returns {*} The timepoint name
|
||||
*/
|
||||
getTimepointName = function(timepoint) {
|
||||
OHIF.measurements.getTimepointName = (timepoint) => {
|
||||
// Check if this is a Baseline timepoint, if it is, return 'Baseline'
|
||||
if (timepoint.timepointType === 'baseline') {
|
||||
return 'Baseline';
|
||||
@ -35,7 +37,7 @@ getTimepointName = function(timepoint) {
|
||||
// If index is 0, it means that the current timepoint was not in the list
|
||||
// Log a warning and return here
|
||||
if (!index) {
|
||||
log.warn('Current follow-up was not in the list of relevant follow-ups?');
|
||||
OHIF.log.warn('Current follow-up was not in the list of relevant follow-ups?');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// TODO: [LT-refactor] move this to ohif:hanging-protocols package
|
||||
|
||||
getTimepointType = function(study) {
|
||||
const timepointApi = Template.instance().timepointApi;
|
||||
if (!timepointApi) {
|
||||
@ -12,8 +14,8 @@ getTimepointType = function(study) {
|
||||
return timepoint.timepointType;
|
||||
};
|
||||
|
||||
const HP = HP || false;
|
||||
HP = HP || false;
|
||||
|
||||
if (HP) {
|
||||
HP.addCustomAttribute('timepointType', 'Timepoint Type', getTimepointType);
|
||||
}
|
||||
HP.addCustomAttribute('timepointType', 'Timepoint Type', getTimepointType);
|
||||
}
|
||||
|
||||
10
Packages/ohif-measurements/client/lib/index.js
Normal file
10
Packages/ohif-measurements/client/lib/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
import './activateLesion.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';
|
||||
import './syncMeasurementAndToolData.js';
|
||||
@ -1,10 +1,12 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
function toolDataExists(toolState, imageId, toolType) {
|
||||
const currentToolState = toolState[imageId][toolType];
|
||||
return (currentToolState && currentToolState.data && currentToolState.data.length);
|
||||
}
|
||||
|
||||
syncMeasurementAndToolData = function(measurement) {
|
||||
log.info('syncMeasurementAndToolData');
|
||||
OHIF.log.info('syncMeasurementAndToolData');
|
||||
|
||||
const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState;
|
||||
const imageId = measurement.imageId;
|
||||
@ -57,4 +59,4 @@ syncMeasurementAndToolData = function(measurement) {
|
||||
|
||||
// Add the MeasurementData into the toolData for this imageId
|
||||
toolState[imageId][toolType].data.push(measurement);
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
// Create package logger using loglevel
|
||||
// https://atmospherejs.com/spacejamio/loglevel
|
||||
log = loglevel.createPackageLogger('measurements', defaultLevel = 'warn');
|
||||
@ -19,19 +19,15 @@ Package.onUse(function(api) {
|
||||
api.use('aldeed:simple-schema');
|
||||
api.use('aldeed:collection2');
|
||||
|
||||
// Control over logging
|
||||
api.use('practicalmeteor:loglevel');
|
||||
|
||||
// Template overriding
|
||||
api.use('aldeed:template-extension@4.0.0');
|
||||
|
||||
// Our custom packages
|
||||
api.use('ohif:cornerstone');
|
||||
api.use('design');
|
||||
api.use('ohif:core');
|
||||
api.use('ohif:log');
|
||||
api.use('ohif:study-list');
|
||||
api.use('ohif:cornerstone');
|
||||
|
||||
api.addFiles('log.js', [ 'client', 'server' ]);
|
||||
|
||||
api.addFiles('both/schema/measurements.js', ['client', 'server']);
|
||||
api.addFiles('both/schema/timepoints.js', ['client', 'server']);
|
||||
@ -39,11 +35,8 @@ Package.onUse(function(api) {
|
||||
api.addFiles('both/configuration/measurements.js', ['client', 'server']);
|
||||
api.addFiles('both/configuration/timepoints.js', ['client', 'server']);
|
||||
|
||||
api.addFiles('client/helpers/measurements.js', ['client']);
|
||||
api.addFiles('client/helpers/timepoints.js', ['client']);
|
||||
|
||||
api.addFiles('client/lib/hangingProtocolCustomizations.js');
|
||||
api.addFiles('client/lib/syncMeasurementAndToolData.js', 'client');
|
||||
// Client imports and routes
|
||||
api.addFiles('client/index.js', 'client');
|
||||
|
||||
// Measurement Table Components
|
||||
api.addFiles('client/components/measurementTable/measurementTable.html', 'client');
|
||||
@ -106,14 +99,5 @@ Package.onUse(function(api) {
|
||||
api.addFiles('client/components/association/confirmRemoveTimepointAssociation/confirmRemoveTimepointAssociation.html', 'client');
|
||||
api.addFiles('client/components/association/confirmRemoveTimepointAssociation/confirmRemoveTimepointAssociation.js', 'client');
|
||||
|
||||
// Client Library functions
|
||||
api.addFiles('client/lib/activateMeasurements.js', 'client');
|
||||
api.addFiles('client/lib/activateLesion.js', 'client');
|
||||
api.addFiles('client/lib/deactivateAllToolData.js', 'client');
|
||||
api.addFiles('client/lib/MeasurementHandlers.js', 'client');
|
||||
api.addFiles('client/lib/MeasurementManager.js', 'client');
|
||||
api.addFiles('client/lib/getTimepointName.js', 'client');
|
||||
api.addFiles('client/lib/getTimepointObject.js', 'client');
|
||||
|
||||
api.export('MeasurementSchemaTypes', ['client', 'server']);
|
||||
});
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
// Create package logger using loglevel
|
||||
// https://atmospherejs.com/spacejamio/loglevel
|
||||
log = loglevel.createPackageLogger('lesiontracker', defaultLevel = 'info');
|
||||
@ -15,9 +15,6 @@ Package.onUse(function(api) {
|
||||
|
||||
api.use('validatejs');
|
||||
|
||||
// Control over logging
|
||||
api.use('practicalmeteor:loglevel');
|
||||
|
||||
// Template overriding
|
||||
api.use('aldeed:template-extension@4.0.0');
|
||||
|
||||
@ -28,11 +25,9 @@ Package.onUse(function(api) {
|
||||
api.use('ohif:cornerstone');
|
||||
api.use('ohif:measurements');
|
||||
|
||||
api.addFiles('log.js', [ 'client', 'server' ]);
|
||||
|
||||
api.addFiles('both/configuration/ellipse.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/measurementTools.js', [ 'client', 'server' ]);
|
||||
|
||||
|
||||
api.addFiles('both/configuration/dataExchange.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/dataValidation.js', [ 'client', 'server' ]);
|
||||
api.addFiles('both/configuration/configuration.js', [ 'client', 'server' ]);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Session.setDefault('showLoadingText', true);
|
||||
|
||||
Template.studylistResult.helpers({
|
||||
@ -149,7 +151,7 @@ function search() {
|
||||
Meteor.call('StudyListSearch', filter, (error, studies) => {
|
||||
console.log('StudyListSearch');
|
||||
if (error) {
|
||||
log.warn(error);
|
||||
OHIF.log.warn(error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
// Maybe we should use regular StudyList collection?
|
||||
StudyListSelectedStudies = new Meteor.Collection(null);
|
||||
StudyListSelectedStudies._debugName = 'StudyListSelectedStudies';
|
||||
|
||||
function handleShiftClick(studyRow, data) {
|
||||
//log.info('shiftKey');
|
||||
//OHIF.log.info('shiftKey');
|
||||
var studyInstanceUid = studyRow.attr('studyInstanceUid');
|
||||
|
||||
// Select all rows in between these two rows
|
||||
@ -60,7 +62,7 @@ function handleShiftClick(studyRow, data) {
|
||||
}
|
||||
|
||||
function handleCtrlClick(studyRow, data) {
|
||||
//log.info('ctrlKey');
|
||||
//OHIF.log.info('ctrlKey');
|
||||
var studyInstanceUid = studyRow.attr('studyInstanceUid');
|
||||
|
||||
if (studyRow.hasClass('active')) {
|
||||
@ -78,7 +80,7 @@ function handleCtrlClick(studyRow, data) {
|
||||
// Set this as the previously selected row, so the user can
|
||||
// use Shift to select from this point onwards
|
||||
StudyList.previouslySelected = studyRow;
|
||||
log.info('StudyList PreviouslySelected set: ' + studyRow.index());
|
||||
OHIF.log.info('StudyList PreviouslySelected set: ' + studyRow.index());
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,7 +115,7 @@ Template.studylistStudy.events({
|
||||
handleCtrlClick(studyRow, data);
|
||||
} else {
|
||||
// Select a single study
|
||||
//log.info('Regular click');
|
||||
//OHIF.log.info('Regular click');
|
||||
|
||||
// Clear all selected studies
|
||||
StudyListSelectedStudies.remove({});
|
||||
@ -121,7 +123,7 @@ Template.studylistStudy.events({
|
||||
|
||||
// Set the previous study to the currently clicked-on study
|
||||
StudyList.previouslySelected = studyRow;
|
||||
//log.info('StudyList PreviouslySelected set: ' + studyRow.index());
|
||||
//OHIF.log.info('StudyList PreviouslySelected set: ' + studyRow.index());
|
||||
|
||||
// Set the current study as selected
|
||||
StudyListSelectedStudies.insert(data);
|
||||
@ -163,4 +165,4 @@ Template.studylistStudy.events({
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Retrieves metaData for multiple studies at once.
|
||||
*
|
||||
@ -50,9 +52,9 @@ getStudiesMetadata = function(studyInstanceUids, doneCallback, failCallback) {
|
||||
doneCallback(studies);
|
||||
}
|
||||
}).fail(function(error) {
|
||||
log.warn(error);
|
||||
OHIF.log.warn(error);
|
||||
if (failCallback && typeof failCallback === 'function') {
|
||||
failCallback(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
// Define the StudyMetaData object. This is used as a cache
|
||||
// to store study meta data information to prevent unnecessary
|
||||
// calls to the server
|
||||
@ -20,7 +22,7 @@ getStudyMetadata = function(studyInstanceUid, doneCallback, failCallback) {
|
||||
doneCallback(study);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
console.time('getStudyMetadata');
|
||||
|
||||
// If no study metadata is in the cache variable, we need to retrieve it from
|
||||
@ -42,7 +44,7 @@ getStudyMetadata = function(studyInstanceUid, doneCallback, failCallback) {
|
||||
}
|
||||
|
||||
if (error) {
|
||||
log.warn(error);
|
||||
OHIF.log.warn(error);
|
||||
failCallback(error);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Imports selected studies from local into studylist
|
||||
* @param filesToImport Files located in the client machine to import
|
||||
@ -44,7 +46,7 @@ importStudies = function(filesToImport, importCallback) {
|
||||
|
||||
if (fileUploadStatus.numberOfFilesFailed > 0) {
|
||||
//TODO: Some files failed to upload, so let user know
|
||||
log.info("Failed to upload " + fileUploadStatus.numberOfFilesFailed + " of " + numberOfFilesToUpload + " files");
|
||||
OHIF.log.info("Failed to upload " + fileUploadStatus.numberOfFilesFailed + " of " + numberOfFilesToUpload + " files");
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -128,4 +130,4 @@ function importStudiesInternal(studiesToImport, importCallback) {
|
||||
// Import studies with study import status id to get callbacks
|
||||
Meteor.call("importStudies", studiesToImport, studyImportStatusId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Switches to a new tab in the tabbed studylist container
|
||||
* This function renders either the StudyList or the Viewer template with new data.
|
||||
@ -9,7 +11,7 @@ switchToTab = function(contentId) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info('Switching to tab: ' + contentId);
|
||||
OHIF.log.info('Switching to tab: ' + contentId);
|
||||
|
||||
$('.tabTitle').removeClass('active');
|
||||
$('.tabTitle a[data-target="#' + contentId + '"]').addClass('active');
|
||||
@ -78,7 +80,7 @@ switchToTab = function(contentId) {
|
||||
function viewStudiesInTab(contentId, studies) {
|
||||
// Tab closed while study data was being retrieved, stop here
|
||||
if (!ViewerData[contentId]) {
|
||||
log.warn('Tab closed while study data was being retrieved');
|
||||
OHIF.log.warn('Tab closed while study data was being retrieved');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
// Create package logger using loglevel
|
||||
// https://atmospherejs.com/spacejamio/loglevel
|
||||
log = loglevel.createPackageLogger('studylist', defaultLevel = 'info');
|
||||
@ -12,7 +12,6 @@ Package.onUse(function (api) {
|
||||
api.use('jquery');
|
||||
api.use('stylus');
|
||||
api.use('http');
|
||||
api.use('practicalmeteor:loglevel');
|
||||
api.use('random');
|
||||
api.use('silentcicero:jszip');
|
||||
api.use('aldeed:simple-schema');
|
||||
@ -35,11 +34,6 @@ Package.onUse(function (api) {
|
||||
// TODO: Replace with NPM dependency
|
||||
api.use('ohif:cornerstone'); // Only for HammerJS
|
||||
|
||||
// This sets the default logging level of the package using the
|
||||
// loglevel package. It can be overridden in the JavaScript
|
||||
// console for debugging purposes
|
||||
api.addFiles('log.js');
|
||||
|
||||
api.addFiles('both/collections.js', ['client', 'server']);
|
||||
api.addFiles('both/schema/servers.js', ['client', 'server']);
|
||||
api.addFiles('both/lib/getCurrentServer.js', ['client', 'server']);
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Meteor.methods({
|
||||
/**
|
||||
* Retrieves Study metadata given a Study Instance UID
|
||||
* This Meteor method is available from both the client and the server
|
||||
*/
|
||||
GetStudyMetadata: function(studyInstanceUid) {
|
||||
log.info('GetStudyMetadata(%s)', studyInstanceUid);
|
||||
OHIF.log.info('GetStudyMetadata(%s)', studyInstanceUid);
|
||||
|
||||
// Get the server data. This is user-defined in the config.json files or through servers
|
||||
// configuration modal
|
||||
|
||||
@ -1,4 +1,20 @@
|
||||
import { parseFloatArray } from '../../lib/parseFloatArray';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { parseFloatArray } from 'meteor/ohif:study-list/server/lib/parseFloatArray';
|
||||
|
||||
/**
|
||||
* Returns the value of the element (e.g. '00280009')
|
||||
*
|
||||
* @param element - The group/element of the element (e.g. '00280009')
|
||||
* @param defaultValue - The default value to return if the element does not exist
|
||||
* @returns {*}
|
||||
*/
|
||||
function getValue(element, defaultValue) {
|
||||
if (!element || !element.value) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return element.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the SourceImageSequence, if it exists, in order
|
||||
@ -18,21 +34,6 @@ function getSourceImageInstanceUid(instance) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the element (e.g. '00280009')
|
||||
*
|
||||
* @param element - The group/element of the element (e.g. '00280009')
|
||||
* @param defaultValue - The default value to return if the element does not exist
|
||||
* @returns {*}
|
||||
*/
|
||||
function getValue(element, defaultValue) {
|
||||
if (!element || !element.value) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return element.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses result data from a DIMSE search into Study MetaData
|
||||
* Returns an object populated with study metadata, including the
|
||||
@ -43,7 +44,7 @@ function getValue(element, defaultValue) {
|
||||
* @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}}
|
||||
*/
|
||||
function resultDataToStudyMetadata(studyInstanceUid, resultData) {
|
||||
log.info('resultDataToStudyMetadata');
|
||||
OHIF.log.info('resultDataToStudyMetadata');
|
||||
var seriesMap = {};
|
||||
var seriesList = [];
|
||||
|
||||
@ -161,4 +162,4 @@ Services.DIMSE.RetrieveMetadata = function(studyInstanceUid) {
|
||||
}
|
||||
|
||||
return resultDataToStudyMetadata(studyInstanceUid, results);
|
||||
};
|
||||
};
|
||||
@ -1,59 +1,59 @@
|
||||
import { moment } from 'meteor/mrt:moment';
|
||||
|
||||
/**
|
||||
* Parses resulting data from a QIDO call into a set of Study MetaData
|
||||
*
|
||||
* @param resultData
|
||||
* @returns {Array} An array of Study MetaData objects
|
||||
*/
|
||||
function resultDataToStudies(resultData) {
|
||||
var studies = [];
|
||||
|
||||
resultData.forEach(function(studyRaw) {
|
||||
var study = studyRaw.toObject();
|
||||
studies.push({
|
||||
studyInstanceUid: study[0x0020000D],
|
||||
// 00080005 = SpecificCharacterSet
|
||||
studyDate: study[0x00080020],
|
||||
studyTime: study[0x00080030],
|
||||
accessionNumber: study[0x00080050],
|
||||
referringPhysicianName: study[0x00080090],
|
||||
// 00081190 = URL
|
||||
patientName: study[0x00100010],
|
||||
patientId: study[0x00100020],
|
||||
patientBirthdate: study[0x00100030],
|
||||
patientSex: study[0x00100040],
|
||||
imageCount: study[0x00201208],
|
||||
studyId: study[0x00200010],
|
||||
studyDescription: study[0x00081030],
|
||||
modalities: study[0x00080061]
|
||||
});
|
||||
});
|
||||
return studies;
|
||||
}
|
||||
|
||||
Services.DIMSE.Studies = function(filter) {
|
||||
log.info('Services.DIMSE.Studies');
|
||||
|
||||
let filterStudyDate = '';
|
||||
if (filter.studyDateFrom && filter.studyDateTo) {
|
||||
const convertDate = date => moment(date, 'MM/DD/YYYY').format('YYYYMMDD');
|
||||
const dateFrom = convertDate(filter.studyDateFrom);
|
||||
const dateTo = convertDate(filter.studyDateTo);
|
||||
filterStudyDate = `${dateFrom}-${dateTo}`;
|
||||
}
|
||||
|
||||
var parameters = {
|
||||
0x00100010: filter.patientName,
|
||||
0x00100020: filter.patientId,
|
||||
0x00080050: filter.accessionNumber,
|
||||
0x00080020: filterStudyDate,
|
||||
0x00081030: filter.studyDescription,
|
||||
0x00100040: '',
|
||||
0x00201208: '',
|
||||
0x00080061: filter.modalitiesInStudy
|
||||
};
|
||||
|
||||
var results = DIMSE.retrieveStudies(parameters);
|
||||
return resultDataToStudies(results);
|
||||
};
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Parses resulting data from a QIDO call into a set of Study MetaData
|
||||
*
|
||||
* @param resultData
|
||||
* @returns {Array} An array of Study MetaData objects
|
||||
*/
|
||||
function resultDataToStudies(resultData) {
|
||||
var studies = [];
|
||||
|
||||
resultData.forEach(function(studyRaw) {
|
||||
var study = studyRaw.toObject();
|
||||
studies.push({
|
||||
studyInstanceUid: study[0x0020000D],
|
||||
// 00080005 = SpecificCharacterSet
|
||||
studyDate: study[0x00080020],
|
||||
studyTime: study[0x00080030],
|
||||
accessionNumber: study[0x00080050],
|
||||
referringPhysicianName: study[0x00080090],
|
||||
// 00081190 = URL
|
||||
patientName: study[0x00100010],
|
||||
patientId: study[0x00100020],
|
||||
patientBirthdate: study[0x00100030],
|
||||
patientSex: study[0x00100040],
|
||||
imageCount: study[0x00201208],
|
||||
studyId: study[0x00200010],
|
||||
studyDescription: study[0x00081030],
|
||||
modalities: study[0x00080061]
|
||||
});
|
||||
});
|
||||
return studies;
|
||||
}
|
||||
|
||||
Services.DIMSE.Studies = function(filter) {
|
||||
OHIF.log.info('Services.DIMSE.Studies');
|
||||
|
||||
let filterStudyDate = '';
|
||||
if (filter.studyDateFrom && filter.studyDateTo) {
|
||||
const convertDate = date => moment(date, 'MM/DD/YYYY').format('YYYYMMDD');
|
||||
const dateFrom = convertDate(filter.studyDateFrom);
|
||||
const dateTo = convertDate(filter.studyDateTo);
|
||||
filterStudyDate = `${dateFrom}-${dateTo}`;
|
||||
}
|
||||
|
||||
var parameters = {
|
||||
0x00100010: filter.patientName,
|
||||
0x00100020: filter.patientId,
|
||||
0x00080050: filter.accessionNumber,
|
||||
0x00080020: filterStudyDate,
|
||||
0x00081030: filter.studyDescription,
|
||||
0x00100040: '',
|
||||
0x00201208: '',
|
||||
0x00080061: filter.modalitiesInStudy
|
||||
};
|
||||
|
||||
var results = DIMSE.retrieveStudies(parameters);
|
||||
return resultDataToStudies(results);
|
||||
};
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
// Create package logger using loglevel
|
||||
// https://atmospherejs.com/spacejamio/loglevel
|
||||
log = loglevel.createPackageLogger('lesiontracker', defaultLevel = 'warn');
|
||||
@ -17,9 +17,6 @@ Package.onUse(function(api) {
|
||||
api.use('aldeed:simple-schema');
|
||||
api.use('aldeed:collection2');
|
||||
|
||||
// Control over logging
|
||||
api.use('practicalmeteor:loglevel');
|
||||
|
||||
// Template overriding
|
||||
api.use('aldeed:template-extension@4.0.0');
|
||||
|
||||
@ -28,8 +25,6 @@ Package.onUse(function(api) {
|
||||
api.use('ohif:core');
|
||||
api.use('ohif:study-list');
|
||||
|
||||
api.addFiles('log.js', [ 'client', 'server' ]);
|
||||
|
||||
api.addFiles('both/collections.js', ['client', 'server']);
|
||||
//api.addFiles('both/schema/reviewers.js', ['client', 'server']);
|
||||
|
||||
|
||||
@ -12,11 +12,11 @@ var allCornerstoneEvents = 'CornerstoneToolsMouseDown CornerstoneToolsMouseDownA
|
||||
* @param data {object} Object containing the study, series, and viewport element to be used
|
||||
*/
|
||||
function loadDisplaySetIntoViewport(data, templateData) {
|
||||
log.info('imageViewerViewport loadDisplaySetIntoViewport');
|
||||
OHIF.log.info('imageViewerViewport loadDisplaySetIntoViewport');
|
||||
|
||||
// Make sure we have all the data required to render the series
|
||||
if (!data.study || !data.displaySet || !data.element) {
|
||||
log.warn('loadDisplaySetIntoViewport: No Study, Display Set, or Element provided');
|
||||
OHIF.log.warn('loadDisplaySetIntoViewport: No Study, Display Set, or Element provided');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ function loadDisplaySetIntoViewport(data, templateData) {
|
||||
|
||||
var numFrames = image.numFrames;
|
||||
if (numFrames > 1) {
|
||||
log.info('Multiframe image detected');
|
||||
OHIF.log.info('Multiframe image detected');
|
||||
for (var i = 0; i < numFrames; i++) {
|
||||
metaData.frame = i;
|
||||
imageId = getImageId(image, i);
|
||||
@ -136,7 +136,7 @@ function loadDisplaySetIntoViewport(data, templateData) {
|
||||
try {
|
||||
enabledElement = cornerstone.getEnabledElement(element);
|
||||
} catch (error) {
|
||||
log.warn('Viewport destroyed before loaded image could be displayed');
|
||||
OHIF.log.warn('Viewport destroyed before loaded image could be displayed');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -239,10 +239,10 @@ function loadDisplaySetIntoViewport(data, templateData) {
|
||||
// Define a function to run whenever the Cornerstone viewport is rendered
|
||||
// (e.g. following a change of window or zoom)
|
||||
function onImageRendered(e, eventData) {
|
||||
log.info('imageViewerViewport onImageRendered');
|
||||
OHIF.log.info('imageViewerViewport onImageRendered');
|
||||
|
||||
if (!layoutManager.viewportData[viewportIndex]) {
|
||||
log.warn("onImageRendered: LayoutManager has no viewport data for this viewport index?: " + 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
|
||||
@ -267,7 +267,7 @@ function loadDisplaySetIntoViewport(data, templateData) {
|
||||
// Define a function to run whenever the Cornerstone viewport changes images
|
||||
// (e.g. during scrolling)
|
||||
function onNewImage(e, eventData) {
|
||||
log.info('imageViewerViewport onNewImage');
|
||||
OHIF.log.info('imageViewerViewport onNewImage');
|
||||
|
||||
// Update the metaData for missing fields
|
||||
updateMetaData(eventData.enabledElement.image);
|
||||
@ -323,7 +323,7 @@ function loadDisplaySetIntoViewport(data, templateData) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info('imageViewerViewport sendActivationTrigger');
|
||||
OHIF.log.info('imageViewerViewport sendActivationTrigger');
|
||||
|
||||
// Otherwise, trigger an 'ActivateViewport' event to be handled by the Template event
|
||||
// handler
|
||||
@ -448,7 +448,7 @@ Meteor.startup(function() {
|
||||
|
||||
Template.imageViewerViewport.onRendered(function() {
|
||||
var templateData = Template.currentData();
|
||||
log.info('imageViewerViewport onRendered');
|
||||
OHIF.log.info('imageViewerViewport onRendered');
|
||||
|
||||
// When the imageViewerViewport template is rendered
|
||||
var element = this.find('.imageViewerViewport');
|
||||
@ -493,7 +493,7 @@ Template.imageViewerViewport.onRendered(function() {
|
||||
});
|
||||
|
||||
Template.imageViewerViewport.onDestroyed(function() {
|
||||
log.info('imageViewerViewport onDestroyed');
|
||||
OHIF.log.info('imageViewerViewport onDestroyed');
|
||||
|
||||
// When a viewport element is being destroyed
|
||||
var element = this.find('.imageViewerViewport');
|
||||
@ -509,7 +509,7 @@ Template.imageViewerViewport.onDestroyed(function() {
|
||||
cornerstoneTools.stopClip(element);
|
||||
}
|
||||
} catch (error) {
|
||||
log.warn(error);
|
||||
OHIF.log.warn(error);
|
||||
}
|
||||
|
||||
// Disable the viewport element with Cornerstone
|
||||
@ -520,7 +520,7 @@ Template.imageViewerViewport.onDestroyed(function() {
|
||||
|
||||
Template.imageViewerViewport.events({
|
||||
'ActivateViewport .imageViewerViewport'(event) {
|
||||
log.info('imageViewerViewport ActivateViewport');
|
||||
OHIF.log.info('imageViewerViewport ActivateViewport');
|
||||
setActiveViewport(event.currentTarget);
|
||||
},
|
||||
|
||||
|
||||
@ -29,10 +29,10 @@ Template.toolbarSectionButton.events({
|
||||
const activeTool = toolManager.getActiveTool();
|
||||
if (tool === activeTool) {
|
||||
const defaultTool = toolManager.getDefaultTool();
|
||||
log.info('Setting active tool to: ' + defaultTool);
|
||||
OHIF.log.info('Setting active tool to: ' + defaultTool);
|
||||
toolManager.setActiveTool(defaultTool, elements);
|
||||
} else {
|
||||
log.info('Setting active tool to: ' + tool);
|
||||
OHIF.log.info('Setting active tool to: ' + tool);
|
||||
toolManager.setActiveTool(tool, elements);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.viewerMain.onCreated(() => {
|
||||
// Attach the Window resize listener
|
||||
// Don't use jQuery here. "window.onresize" will always be null
|
||||
@ -28,8 +30,8 @@ Template.viewerMain.onRendered(() => {
|
||||
});
|
||||
|
||||
Template.viewerMain.onDestroyed(() => {
|
||||
log.info('viewerMain onDestroyed');
|
||||
|
||||
OHIF.log.info('viewerMain onDestroyed');
|
||||
|
||||
// Remove the Window resize listener
|
||||
window.removeEventListener('resize', handleResize);
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
applyWLPreset = function(presetName, element) {
|
||||
log.info("Applying WL Preset: " + presetName);
|
||||
OHIF.log.info("Applying WL Preset: " + presetName);
|
||||
var viewport = cornerstone.getViewport(element);
|
||||
|
||||
if (presetName === 'Default') {
|
||||
|
||||
@ -8,7 +8,7 @@ import { OHIF } from 'meteor/ohif:core';
|
||||
* @param element {node} DOM Node representing the viewport element
|
||||
*/
|
||||
displayReferenceLines = element => {
|
||||
log.info("imageViewerViewport displayReferenceLines");
|
||||
OHIF.log.info("imageViewerViewport displayReferenceLines");
|
||||
|
||||
// Check if image plane (orientation / loction) data is present for the current image
|
||||
const enabledElement = cornerstone.getEnabledElement(element);
|
||||
|
||||
@ -214,7 +214,7 @@ Meteor.startup(function() {
|
||||
$.fn.reverse = [].reverse;
|
||||
|
||||
function previousActivePanel() {
|
||||
log.info('nextActivePanel');
|
||||
OHIF.log.info('nextActivePanel');
|
||||
var currentIndex = Session.get('activeViewport');
|
||||
currentIndex--;
|
||||
|
||||
@ -233,7 +233,7 @@ function previousActivePanel() {
|
||||
}
|
||||
|
||||
function nextActivePanel() {
|
||||
log.info('nextActivePanel');
|
||||
OHIF.log.info('nextActivePanel');
|
||||
var currentIndex = Session.get('activeViewport');
|
||||
currentIndex++;
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* This function enables stack prefetching for a specified element (viewport)
|
||||
* It first disables any prefetching currently occurring on any other viewports.
|
||||
@ -5,7 +7,7 @@
|
||||
* @param element {node} DOM Node representing the viewport element
|
||||
*/
|
||||
enablePrefetchOnElement = function(element) {
|
||||
log.info("imageViewerViewport enablePrefetchOnElement");
|
||||
OHIF.log.info("imageViewerViewport enablePrefetchOnElement");
|
||||
|
||||
// Loop through all viewports and disable stackPrefetch
|
||||
$('.imageViewerViewport').each(function() {
|
||||
@ -20,4 +22,4 @@ enablePrefetchOnElement = function(element) {
|
||||
if (stack && stack.data.length && stack.data[0].imageIds.length > 1) {
|
||||
cornerstoneTools.stackPrefetch.enable(element);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Obtain an imageId for Cornerstone based on the WADO-RS scheme
|
||||
*
|
||||
@ -55,6 +57,6 @@ getWADORSImageId = function(instance) {
|
||||
|
||||
var imageId = cornerstoneWADOImageLoader.imageManager.add(image);
|
||||
|
||||
log.info('WADO-RS ImageID: ' + imageId);
|
||||
OHIF.log.info('WADO-RS ImageID: ' + imageId);
|
||||
return imageId;
|
||||
};
|
||||
|
||||
@ -3,7 +3,7 @@ import { OHIF } from 'meteor/ohif:core';
|
||||
// Displays Series in Viewports given a Protocol and list of Studies
|
||||
LayoutManager = class LayoutManager {
|
||||
constructor(parentNode, studies) {
|
||||
log.info('LayoutManager');
|
||||
OHIF.log.info('LayoutManager');
|
||||
|
||||
this.parentNode = parentNode;
|
||||
this.studies = studies;
|
||||
@ -99,7 +99,7 @@ LayoutManager = class LayoutManager {
|
||||
}
|
||||
|
||||
updateViewports() {
|
||||
log.info('updateViewports');
|
||||
OHIF.log.info('updateViewports');
|
||||
|
||||
if (!this.viewportData ||
|
||||
!this.viewportData.length ||
|
||||
@ -176,7 +176,7 @@ LayoutManager = class LayoutManager {
|
||||
}
|
||||
|
||||
enlargeViewport(viewportIndex) {
|
||||
log.info('Zooming Into Viewport: ' + viewportIndex);
|
||||
OHIF.log.info('Zooming Into Viewport: ' + viewportIndex);
|
||||
|
||||
if (!this.viewportData ||
|
||||
!this.viewportData.length) {
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
// Create package logger using loglevel
|
||||
// https://atmospherejs.com/spacejamio/loglevel
|
||||
log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'warn');
|
||||
@ -12,7 +12,6 @@ Package.onUse(function(api) {
|
||||
api.use('http');
|
||||
api.use('jquery');
|
||||
api.use('stylus');
|
||||
api.use('practicalmeteor:loglevel');
|
||||
api.use('momentjs:moment');
|
||||
api.use('validatejs');
|
||||
|
||||
@ -21,8 +20,6 @@ Package.onUse(function(api) {
|
||||
api.use('ohif:core');
|
||||
api.use('ohif:cornerstone');
|
||||
|
||||
api.addFiles('log.js');
|
||||
|
||||
api.addAssets('assets/icons.svg', 'client');
|
||||
|
||||
// TODO: Use NPM depends for these
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -34,10 +34,10 @@ Template.viewer.onCreated(() => {
|
||||
const contentId = instance.data.contentId;
|
||||
|
||||
if (ViewerData[contentId] && ViewerData[contentId].loadedSeriesData) {
|
||||
log.info('Reloading previous loadedSeriesData');
|
||||
OHIF.log.info('Reloading previous loadedSeriesData');
|
||||
OHIF.viewer.loadedSeriesData = ViewerData[contentId].loadedSeriesData;
|
||||
} else {
|
||||
log.info('Setting default ViewerData');
|
||||
OHIF.log.info('Setting default ViewerData');
|
||||
OHIF.viewer.loadedSeriesData = {};
|
||||
ViewerData[contentId] = {};
|
||||
ViewerData[contentId].loadedSeriesData = OHIF.viewer.loadedSeriesData;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user