PWV-3: Creating ohif:log package and partially refactoring ohif:measurements

This commit is contained in:
Bruno Alves de Faria 2016-09-20 17:47:44 -03:00 committed by Erik Ziegler
parent f3f32518c6
commit 60aa1d0982
76 changed files with 410 additions and 479 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -1,6 +1,6 @@
import './lib';
import './components';
import './helpers';
import './components';
import './ui';
import './routes.js';

View File

@ -3,6 +3,7 @@
*/
const OHIF = {
log: {},
viewer: {},
measurements: {}
};

View 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
};

View File

@ -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');
});

View File

@ -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);
}

View File

@ -1,3 +0,0 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createPackageLogger('hangingprotocols', defaultLevel = 'info');

View File

@ -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

View File

@ -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);
}
});
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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);
}
};
};

View File

@ -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);

View File

@ -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);
};
};

View File

@ -1,3 +0,0 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createPackageLogger('lesiontracker', defaultLevel = 'info');

View File

@ -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');

View 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);

View 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' ]);
});

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
},*/
});

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -0,0 +1 @@
import './measurements.js';

View File

@ -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();
});

View File

@ -1,5 +0,0 @@
Template.registerHelper('getTimepointName', timepoint => {
const instance = Template.instance()
const timepointApi = instance.data.timepointApi;
return timepointApi.name(timepoint);
});

View File

@ -0,0 +1,4 @@
import './lib';
import './helpers';
// import './components';
// import './ui';

View File

@ -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;

View File

@ -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);
});
});

View File

@ -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);
}

View 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);
};

View File

@ -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({});
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View 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';

View File

@ -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);
};
};

View File

@ -1,3 +0,0 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createPackageLogger('measurements', defaultLevel = 'warn');

View File

@ -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']);
});

View File

@ -1,3 +0,0 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createPackageLogger('lesiontracker', defaultLevel = 'info');

View File

@ -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' ]);

View File

@ -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;
}

View File

@ -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({
}
}
});
});

View File

@ -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);
}
});
};
};

View File

@ -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;
}

View File

@ -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);
});
}
}

View File

@ -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;
}

View File

@ -1,3 +0,0 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createPackageLogger('studylist', defaultLevel = 'info');

View File

@ -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']);

View File

@ -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

View File

@ -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);
};
};

View File

@ -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);
};

View File

@ -1,3 +0,0 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createPackageLogger('lesiontracker', defaultLevel = 'warn');

View File

@ -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']);

View File

@ -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);
},

View File

@ -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);
}
},

View File

@ -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);

View File

@ -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') {

View File

@ -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);

View File

@ -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++;

View File

@ -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);
}
};
};

View File

@ -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;
};

View File

@ -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) {

View File

@ -1,3 +0,0 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'warn');

View File

@ -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

View File

@ -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;