Commented a lot of functions. Tried to get jsDoc and/or docco to work

This commit is contained in:
Erik Ziegler committed 2015-11-16 17:49:35 +01:00
1 parent 14f47ad0e3
commit f349572d53
46 files changed
+654 -274

No files matched your search

@@ -190,9 +190,11 @@ function loadSeriesIntoViewport(data) {
// Add stack state managers for the stack tool, CINE tool, and reference lines
cornerstoneTools.addStackStateManager(element, [ 'stack', 'playClip', 'referenceLines' ]);
// Enable orientation markers, if applicable
// Get the current viewport settings
var viewport = cornerstone.getViewport(element);
updateOrientationMarkers(element, viewport);
// Enable orientation markers, if applicable
updateOrientationMarkers(element);
// Clear any old stack data
cornerstoneTools.clearToolState(element, 'stack');
@@ -1,3 +1,10 @@
/**
* Adds the 'hover' class to cells above and to the left of the current cell
* This is used to "fill in" the grid that the user will change the layout to,
* if they click on a specific table cell.
*
* @param currentCell
*/
function highlightCells(currentCell) {
var cells = $('.layoutChooser table td');
cells.removeClass('hover');
@@ -1,5 +1,13 @@
updateOrientationMarkers = function(element, viewport) {
// Updates the orientation labels on the viewport
/**
* Updates the orientation labels on a Cornerstone-enabled Viewport element
* when the viewport settings change (e.g. when a horizontal flip or a rotation occurs)
*
* @param element The DOM element of the Cornerstone viewport
*/
updateOrientationMarkers = function(element) {
// Get the current viewport settings
var viewport = cornerstone.getViewport(element);
var enabledElement = cornerstone.getEnabledElement(element);
var imagePlane = cornerstoneTools.metaData.get('imagePlane', enabledElement.image.imageId);
+18
View File
@@ -1,7 +1,22 @@
/**
* Creates a set of series to be placed in the Study Browser
* The series that appear in the Study Browser must represent
* imaging modalities.
*
* Furthermore, for drag/drop functionality,
* it is easiest if the stack objects also contain information about
* which study they are linked to.
*
* @param study The study instance to be used
* @returns {Array} An array of series to be placed in the Study Browser
*/
createStacks = function(study) {
// Define an empty array of stacks
var stacks = [];
// TODO: Split by multi-frame, modality, image size, etc
study.seriesList.forEach(function(series) {
// If the series has no instanced, skip it
if (!series.instances) {
return;
}
@@ -13,7 +28,10 @@ createStacks = function(study) {
return;
}
// Include the study instance Uid for drag/drop purposes
series.studyInstanceUid = study.studyInstanceUid;
// Add this series to the list of stacks
stacks.push(series);
});
return stacks;
@@ -1,6 +1,4 @@
(function($) {
//Collapse the container
function collapseContainer ( container ) {
container.toggleClass("collapseHorizontal");
+4 -3
View File
@@ -8,10 +8,11 @@
encodeQueryData = function(data)
{
var ret = [];
for (var d in data) {
if(data[d]) {
ret.push(encodeURIComponent(d) + "=" + encodeURIComponent(data[d]));
}
if(data[d]) {
ret.push(encodeURIComponent(d) + "=" + encodeURIComponent(data[d]));
}
}
return ret.join("&");
};
@@ -1,39 +0,0 @@
function checkToken(token, data, dataOffset) {
if(dataOffset + token.length > data.length) {
//console.log('dataOffset >> ', dataOffset);
return false;
}
var endIndex = dataOffset;
for(var i = 0; i < token.length; i++) {
if(token[i] !== data[endIndex++]) {
if(endIndex > 520000) {
console.log('token=',uint8ArrayToString(token));
console.log('data=', uint8ArrayToString(data, dataOffset, endIndex-dataOffset));
console.log('miss at %d %s dataOffset=%d', i, String.fromCharCode(data[endIndex]), endIndex);
console.log('miss at %d %s dataOffset=%d', i, String.fromCharCode(token[endIndex]), endIndex);
}
return false;
}
}
return true;
}
findIndexOfString = function(data, str, offset) {
offset = offset || 0;
var token = stringToUint8Array(str);
for(var i=offset; i < data.length; i++) {
if(token[0] === data[i]) {
//console.log('match @', i);
if(checkToken(token, data, i)) {
return i;
}
}
}
return -1;
}
@@ -1,5 +0,0 @@
getActiveViewportElement = function() {
// TODO: Fix this, just hardcoded for now
var element = $('.imageViewerViewport').get(0);
return element;
};
+6
View File
@@ -1,3 +1,9 @@
/**
* Obtain an imageId for Cornerstone from an image instance
*
* @param instance
* @returns {string} The imageId to be used by Cornerstone
*/
getImageId = function(instance) {
if (!instance) {
return;
@@ -1,3 +1,10 @@
/**
* Obtain an imageId for Cornerstone based on the WADO-RS scheme
*
* @param instance
* @returns {string} The imageId to be used by Cornerstone
*/
getWADORSImageId = function(instance) {
var columnPixelSpacing = 1.0;
var rowPixelSpacing = 1.0;
+4 -2
View File
@@ -1,9 +1,11 @@
/**
* A global Blaze UI helper function to format DICOM Dates using the Moment library
*/
UI.registerHelper('formatDA', function (context, format, options) {
if (!context) {
return undefined;
}
var date = context;
var dateAsMoment = moment(date, "YYYYMMDD");
var dateAsMoment = moment(context, "YYYYMMDD");
var strFormat = "MMM D, YYYY";
if (options) {
strFormat = format;
@@ -1,4 +1,7 @@
UI.registerHelper('formatNumberPrecision', function(context, precision, options) {
/**
* A global Blaze UI helper to format a float value to a specified precision
*/
UI.registerHelper('formatNumberPrecision', function(context, precision) {
if (context) {
return parseFloat(context).toFixed(precision);
}
+5 -3
View File
@@ -1,7 +1,9 @@
UI.registerHelper('formatPN', function (context, format, options) {
/**
* A global Blaze UI helper to format a patient name for display purposes
*/
UI.registerHelper('formatPN', function (context) {
if (!context) {
return undefined;
}
var patientName = context.replace('^', ', ');
return patientName;
return context.replace('^', ', ');
});
+5 -4
View File
@@ -1,13 +1,14 @@
UI.registerHelper('formatTM', function(context, format, options) {
/**
* A global Blaze UI helper to format a DICOM Time for display using the Moment library
*/
UI.registerHelper('formatTM', function(context, format) {
if (!context) {
return undefined;
}
var date = context;
var dateAsMoment = moment(date);
var dateAsMoment = moment(context);
var strFormat = "HH:mm:ss";
if (options) {
strFormat = format;
}
return dateAsMoment.format(strFormat);
});
+8
View File
@@ -1,3 +1,11 @@
/**
* Helper function to determine if the current client devices
* is touch-capable. This can be used to modify certain aspects of the UI.
*
* The check may not work on all devices!
*
* @returns {boolean} true if the client device is touch-capable, false otherwise
*/
isTouchDevice = function() {
return (('ontouchstart' in window) ||
(navigator.MaxTouchPoints > 0) ||
@@ -1,5 +1,17 @@
var metaDataLookup = {};
/**
* Cornerstone MetaData provider to store image meta data
* Data from instances, series, and studies are associated with
* imageIds to facilitate usage of this information by Cornerstone's Tools
*
* e.g. the imagePlane metaData object contains instance information about
* row/column pixel spacing, patient position, and patient orientation. It
* is used in CornerstoneTools to position reference lines and orientation markers.
*
* @param {String} imageId The Cornerstone ImageId
* @param {Object} data An object containing instance, series, and study metaData
*/
addMetaData = function(imageId, data) {
var instanceMetaData = data.instance;
var seriesMetaData = data.series;
@@ -72,6 +84,15 @@ addMetaData = function(imageId, data) {
metaDataLookup[imageId] = metaData;
};
/**
* Looks up metaData for Cornerstone Tools given a specified type and imageId
* A type may be, e.g. 'study', or 'patient', or 'imagePlane'. These types
* are keys in the stored metaData objects.
*
* @param type
* @param imageId
* @returns {Object} Relevant metaData of the specified type
*/
function provider(type, imageId) {
var imageMetaData = metaDataLookup[imageId];
if (!imageMetaData) {
@@ -1,5 +1,5 @@
/**
* This function destroys and rerenders the imageViewerViewport template.
* This function destroys and re-renders the imageViewerViewport template.
* It uses the data provided (object containing seriesIndex and studyIndex) to
* load a new series into the produced viewport.
*
@@ -7,8 +7,12 @@
* @param data An object containing a seriesIndex and studyIndex for a study to load into this viewport
*/
rerenderViewportWithNewSeries = function(element, data) {
// Get the container and index of the current viewport.
// The parent container is identified because it is later removed from the DOM
var container = $(element).parents('.viewportContainer').get(0);
var viewportIndex = $(container).index();
// Record the current viewportIndex so this can be passed into the re-rendering call
data.viewportIndex = viewportIndex;
// Update the dictionary of loaded series for the specified viewport
+6
View File
@@ -1,3 +1,9 @@
/**
* Sorts the series and instances inside a study instance by their series
* and instance numbers in ascending order.
*
* @param {Object} study The study instance
*/
sortStudy = function(study) {
if (!study) {
return;
@@ -1,7 +1 @@
stringToUint8Array = function(str) {
var uint=new Uint8Array(str.length);
for(var i=0,j=str.length;i<j;i++){
uint[i]=str.charCodeAt(i);
}
return uint;
};
@@ -1,9 +0,0 @@
uint8ArrayToString = function(data, offset, length) {
offset = offset || 0;
length = length || data.length - offset;
var str = "";
for(var i=offset; i < offset + length; i++) {
str += String.fromCharCode(data[i]);
}
return str;
};
@@ -1,5 +1,13 @@
updateOrientationMarkers = function(element, viewport) {
// Updates the orientation labels on the viewport
/**
* Updates the orientation labels on a Cornerstone-enabled Viewport element
* when the viewport settings change (e.g. when a horizontal flip or a rotation occurs)
*
* @param element The DOM element of the Cornerstone viewport
*/
updateOrientationMarkers = function(element) {
// Get the current viewport settings
var viewport = cornerstone.getViewport(element);
var enabledElement = cornerstone.getEnabledElement(element);
var imagePlane = cornerstoneTools.metaData.get('imagePlane', enabledElement.image.imageId);
@@ -14,7 +22,7 @@ updateOrientationMarkers = function(element, viewport) {
var markers = {
top: oppositeColumnString,
left: oppositeRowString,
left: oppositeRowString
};
// If any vertical or horizontal flips are applied, change the orientation strings ahead of
+1 -1
View File
@@ -1,3 +1,3 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'warn');
log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'info');
-9
View File
@@ -95,33 +95,24 @@ Package.onUse(function (api) {
api.addFiles('lib/accountsConfig.js', 'client');
api.addFiles('lib/createStacks.js', 'client');
api.addFiles('lib/encodeQueryData.js', ['client', 'server']);
api.addFiles('lib/findIndexOfString.js', 'client');
api.addFiles('lib/getActiveViewportElement.js', 'client');
api.addFiles('lib/getImageId.js', 'client');
api.addFiles('lib/getWADORSImageId.js', 'client');
api.addFiles('lib/isTouchDevice.js', 'client');
api.addFiles('lib/metaDataProvider.js', 'client');
api.addFiles('lib/rerenderViewportWithNewSeries.js', 'client');
api.addFiles('lib/sortStudy.js', 'client');
api.addFiles('lib/stringToUint8Array.js', 'client');
api.addFiles('lib/toolManager.js', 'client');
api.addFiles('lib/uint8ArrayToString.js', 'client');
api.addFiles('lib/updateOrientationMarkers.js', 'client');
//api.export('accountsConfig', 'client');
api.export('createStacks', 'client');
api.export('encodeQueryData', ['client', 'server']);
api.export('findIndexOfString', 'client');
api.export('getActiveViewportElement', 'client');
api.export('getImageId', 'client');
api.export('getWADORSImageId', 'client');
api.export('isTouchDevice', 'client');
api.export('metaDataProvider', 'client');
api.export('rerenderViewportWithNewSeries', 'client');
api.export('sortStudy', 'client');
api.export('stringToUint8Array', 'client');
api.export('toolManager', 'client');
api.export('uint8ArrayToString', 'client');
api.export('updateOrientationMarkers', 'client');
// UI Helpers
@@ -1,10 +1,15 @@
Meteor.methods({
'GetStudyMetadata' : function(studyInstanceUid) {
log.info('GetStudyMetadata(%s)', studyInstanceUid);
/**
* 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);
var server = Meteor.settings.dicomWeb.endpoints[0];
// Get the server data. This is user-defined in the
// config.json files used to run the Meteor server
var server = Meteor.settings.dicomWeb.endpoints[0];
//return Services.QIDO.Instances(server, studyInstanceUid);
return Services.WADO.RetrieveMetadata(server, studyInstanceUid);
}
return Services.WADO.RetrieveMetadata(server, studyInstanceUid);
}
});
@@ -1,6 +1,13 @@
Meteor.methods({
'WorklistSearch' : function(filter) {
var server = Meteor.settings.dicomWeb.endpoints[0];
return Services.QIDO.Studies(server, filter);
}
/**
* Use the specified filter to conduct a search from the DICOM server
* @param filter
*/
'WorklistSearch': function(filter) {
// Get the server data. This is user-defined in the
// config.json files used to run the Meteor server
var server = Meteor.settings.dicomWeb.endpoints[0];
return Services.QIDO.Studies(server, filter);
}
});
@@ -1,59 +1,83 @@
/**
* Creates a QIDO URL given the server settings and a study instance UID
* @param server
* @param studyInstanceUid
* @returns {string} URL to be used for QIDO calls
*/
function buildUrl(server, studyInstanceUid) {
var url = server.qidoRoot + '/studies/' + studyInstanceUid + '/instances';
return url;
return server.qidoRoot + '/studies/' + studyInstanceUid + '/instances';
}
/**
* Parses data returned from a QIDO search and transforms it into
* an array of series that are present in the study
*
* @param server The DICOM server
* @param studyInstanceUid
* @param resultData
* @returns {Array} Series List
*/
function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
var seriesMap = {};
var seriesList = [];
resultData.forEach(function(instance) {
var seriesInstanceUid = DICOMWeb.getString(instance['0020000E']);
var series = seriesMap[seriesInstanceUid];
if(!series) {
series = {
seriesInstanceUid : seriesInstanceUid,
seriesNumber : DICOMWeb.getString(instance['00200011']),
instances: []
};
seriesMap[seriesInstanceUid] = series;
seriesList.push(series);
}
var seriesMap = {};
var seriesList = [];
// The uri for the dicomweb
// NOTE: DCM4CHEE seems to return the data zipped
// NOTE: Orthanc returns the data with multi-part mime which cornerstoneWADOImageLoader doesn't
// know how to parse yet
//var uri = DICOMWeb.getString(instance['00081190']);
//uri = uri.replace('wado-rs', 'dicom-web');
resultData.forEach(function(instance) {
// Use seriesMap to cache series data
// If the series instance UID has already been used to
// process series data, continue using that series
var seriesInstanceUid = DICOMWeb.getString(instance['0020000E']);
var series = seriesMap[seriesInstanceUid];
// manually create a WADO-URI from the UID's
// NOTE: Haven't been able to get Orthanc's WADO-URI to work yet - maybe its not configured?
var sopInstanceUid = DICOMWeb.getString(instance['00080018']);
var uri = server.wadoUriRoot + '?requestType=WADO&studyUID=' + studyInstanceUid + '&seriesUID=' + seriesInstanceUid + '&objectUID=' + sopInstanceUid + "&contentType=application%2Fdicom";
// If no series data exists in the seriesMap cache variable,
// process any available series data
if(!series) {
series = {
seriesInstanceUid : seriesInstanceUid,
seriesNumber : DICOMWeb.getString(instance['00200011']),
instances: []
};
series.instances.push({
sopClassUid: DICOMWeb.getString(instance['00080016']),
sopInstanceUid: sopInstanceUid,
uri: uri,
instanceNumber: DICOMWeb.getString(instance['00200013'])
});
// Save this data in the seriesMap cache variable
seriesMap[seriesInstanceUid] = series;
seriesList.push(series);
}
// The uri for the dicomweb
// NOTE: DCM4CHEE seems to return the data zipped
// NOTE: Orthanc returns the data with multi-part mime which cornerstoneWADOImageLoader doesn't
// know how to parse yet
//var uri = DICOMWeb.getString(instance['00081190']);
//uri = uri.replace('wado-rs', 'dicom-web');
// manually create a WADO-URI from the UIDs
// NOTE: Haven't been able to get Orthanc's WADO-URI to work yet - maybe its not configured?
var sopInstanceUid = DICOMWeb.getString(instance['00080018']);
var uri = server.wadoUriRoot + '?requestType=WADO&studyUID=' + studyInstanceUid + '&seriesUID=' + seriesInstanceUid + '&objectUID=' + sopInstanceUid + "&contentType=application%2Fdicom";
// Add this instance to the current series
series.instances.push({
sopClassUid: DICOMWeb.getString(instance['00080016']),
sopInstanceUid: sopInstanceUid,
uri: uri,
instanceNumber: DICOMWeb.getString(instance['00200013'])
});
});
return seriesList;
}
/**
* Retrieve a set of instances using a QIDO call
* @param server
* @param studyInstanceUid
* @returns {{wadoUriRoot: String, studyInstanceUid: String, seriesList: Array}}
*/
Services.QIDO.Instances = function(server, studyInstanceUid) {
var url = buildUrl(server, studyInstanceUid);
var result = DICOMWeb.getJSON(url, server.requestOptions);
var url = buildUrl(server, studyInstanceUid);
var result = DICOMWeb.getJSON(url, server.requestOptions);
var study = {
wadoUriRoot: server.wadoUriRoot,
studyInstanceUid: studyInstanceUid,
seriesList: resultDataToStudyMetadata(server, studyInstanceUid, result.data)
};
return study;
return {
wadoUriRoot: server.wadoUriRoot,
studyInstanceUid: studyInstanceUid,
seriesList: resultDataToStudyMetadata(server, studyInstanceUid, result.data)
};
};
@@ -1,45 +1,56 @@
/**
* Produces a QIDO URL given server details and a set of specified search filter
* items
*
* @param server
* @param filter
* @returns {string} The URL with encoded filter query data
*/
function filterToQIDOURL(server, filter) {
var parameters = {
PatientName : filter.patientName,
PatientID: filter.patientId,
AccessionNumber : filter.accessionNumber,
limit : filter.limit || 20,
includefield : server.qidoSupportsIncludeField ? 'all' : undefined
};
var url = server.qidoRoot + '/studies?' + encodeQueryData(parameters);
return url;
var parameters = {
PatientName : filter.patientName,
PatientID: filter.patientId,
AccessionNumber : filter.accessionNumber,
limit : filter.limit || 20,
includefield : server.qidoSupportsIncludeField ? 'all' : undefined
};
return server.qidoRoot + '/studies?' + encodeQueryData(parameters);
}
/**
* 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(study) {
studies.push({
studyInstanceUid: DICOMWeb.getString(study['0020000D']),
// 00080005 = SpecificCharacterSet
studyDate: DICOMWeb.getString(study['00080020']),
studyTime: DICOMWeb.getString(study['00080030']),
accessionNumber: DICOMWeb.getString(study['00080050']),
referringPhysicianName: DICOMWeb.getString(study['00080090']),
// 00081190 = URL
patientName: DICOMWeb.getName(study['00100010']),
patientId: DICOMWeb.getString(study['00100020']),
patientBirthdate: DICOMWeb.getString(study['00100030']),
patientSex: DICOMWeb.getString(study['00100040']),
imageCount: DICOMWeb.getString(study['00201208']),
studyId: DICOMWeb.getString(study['00200010']),
studyDescription: DICOMWeb.getString(study['00081030']),
modalities: DICOMWeb.getString(study['00080061'])
//url : server.wadoRoot + '/studies/' + DICOMWeb.getString(study['0020000D']) + '/metadata'
var studies = [];
resultData.forEach(function(study) {
studies.push({
studyInstanceUid: DICOMWeb.getString(study['0020000D']),
// 00080005 = SpecificCharacterSet
studyDate: DICOMWeb.getString(study['00080020']),
studyTime: DICOMWeb.getString(study['00080030']),
accessionNumber: DICOMWeb.getString(study['00080050']),
referringPhysicianName: DICOMWeb.getString(study['00080090']),
// 00081190 = URL
patientName: DICOMWeb.getName(study['00100010']),
patientId: DICOMWeb.getString(study['00100020']),
patientBirthdate: DICOMWeb.getString(study['00100030']),
patientSex: DICOMWeb.getString(study['00100040']),
imageCount: DICOMWeb.getString(study['00201208']),
studyId: DICOMWeb.getString(study['00200010']),
studyDescription: DICOMWeb.getString(study['00081030']),
modalities: DICOMWeb.getString(study['00080061'])
});
});
});
return studies;
return studies;
}
Services.QIDO.Studies = function(server, filter) {
var url = filterToQIDOURL(server, filter);
var result = DICOMWeb.getJSON(url, server.requestOptions);
return resultDataToStudies(result.data);
var url = filterToQIDOURL(server, filter);
var result = DICOMWeb.getJSON(url, server.requestOptions);
return resultDataToStudies(result.data);
};
@@ -1,8 +1,22 @@
/**
* Creates a URL for a WADO search
*
* @param server
* @param studyInstanceUid
* @returns {string}
*/
function buildUrl(server, studyInstanceUid) {
var url = server.wadoRoot + '/studies/' + studyInstanceUid + '/metadata';
return url;
return server.wadoRoot + '/studies/' + studyInstanceUid + '/metadata';
}
/**
* Parses the SourceImageSequence, if it exists, in order
* to return a ReferenceSOPInstanceUID. The ReferenceSOPInstanceUID
* is used to refer to this image in any accompanying DICOM-SR documents.
*
* @param instance
* @returns {String} The ReferenceSOPInstanceUID
*/
function getSourceImageInstanceUid(instance) {
// TODO= Parse the whole Source Image Sequence
// This is a really poor workaround for now.
@@ -13,6 +27,16 @@ function getSourceImageInstanceUid(instance) {
}
}
/**
* Parses result data from a WADO search into Study MetaData
* Returns an object populated with study metadata, including the
* series list.
*
* @param server
* @param studyInstanceUid
* @param resultData
* @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}}
*/
function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
var seriesMap = {};
var seriesList = [];
@@ -92,6 +116,12 @@ function resultDataToStudyMetadata(server, studyInstanceUid, resultData) {
return studyData;
}
/**
* Retrieved Study MetaData from a DICOM server using a WADO call
* @param server
* @param studyInstanceUid
* @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}}
*/
Services.WADO.RetrieveMetadata = function(server, studyInstanceUid) {
var url = buildUrl(server, studyInstanceUid);