Update CornerstoneWADOImageLoader to 0.9.0, tried to get DIMSE + WADO-URI working

This commit is contained in:
Erik Ziegler 2016-02-09 13:19:11 +01:00
parent da5e752097
commit 8297171f4a
9 changed files with 103 additions and 66 deletions

View File

@ -1,5 +1,5 @@
Meteor.startup(function() { Meteor.startup(function() {
if (Meteor.settings) { if (Object.keys(Meteor.settings).length > 1) {
console.log('Using custom LesionTracker settings'); console.log('Using custom LesionTracker settings');
console.log(Meteor.settings); console.log(Meteor.settings);
return; return;

View File

@ -1,5 +1,5 @@
Meteor.startup(function() { Meteor.startup(function() {
if (Meteor.settings) { if (Object.keys(Meteor.settings).length > 1) {
console.log('Using custom LesionTracker settings: '); console.log('Using custom LesionTracker settings: ');
console.log(Meteor.settings); console.log(Meteor.settings);
return; return;

View File

@ -1,4 +1,4 @@
/*! cornerstone-wado-image-loader - v0.8.1 - 2016-02-07 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstoneWADOImageLoader */ /*! cornerstone-wado-image-loader - v0.9.0 - 2016-02-08 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstoneWADOImageLoader */
// //
// This is a cornerstone image loader for WADO-URI requests. It has limited support for compressed // This is a cornerstone image loader for WADO-URI requests. It has limited support for compressed
// transfer syntaxes, check here to see what is currently supported: // transfer syntaxes, check here to see what is currently supported:
@ -85,10 +85,10 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
throw "no color space conversion for photometric interpretation " + photometricInterpretation; throw "no color space conversion for photometric interpretation " + photometricInterpretation;
} }
deferred.resolve(imageData); deferred.resolve(imageData);
return deferred; return deferred.promise();
} catch (error) { } catch (error) {
deferred.reject(error); deferred.reject(error);
return deferred; return deferred.promise();
} }
} }
@ -380,7 +380,7 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
} }
}; };
return deferred; return deferred.promise();
} }
function isJPEGBaseline8Bit(dataSet) { function isJPEGBaseline8Bit(dataSet) {
@ -550,6 +550,11 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
else if( transferSyntax === "1.2.840.10008.1.2.1") { else if( transferSyntax === "1.2.840.10008.1.2.1") {
return cornerstoneWADOImageLoader.extractUncompressedPixels(dataSet, frame); return cornerstoneWADOImageLoader.extractUncompressedPixels(dataSet, frame);
} }
// Explicit VR Big Endian (retired)
else if ( transferSyntax === "1.2.840.10008.1.2.2" )
{
return cornerstoneWADOImageLoader.extractUncompressedPixels(dataSet, frame, true);
}
// JPEG 2000 Lossless // JPEG 2000 Lossless
else if(transferSyntax === "1.2.840.10008.1.2.4.90") else if(transferSyntax === "1.2.840.10008.1.2.4.90")
{ {
@ -599,6 +604,9 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
} }
else else
{ {
if(console && console.log) {
console.log("Image cannot be decoded due to Unsupported transfer syntax " + transferSyntax);
}
throw "no decoder for transfer syntax " + transferSyntax; throw "no decoder for transfer syntax " + transferSyntax;
} }
} }
@ -3288,17 +3296,37 @@ var JpegImage = (function jpegImage() {
(function ($, cornerstone, cornerstoneWADOImageLoader) { (function ($, cornerstone, cornerstoneWADOImageLoader) {
"use strict"; "use strict";
function extractUncompressedPixels(dataSet, frame)
function swap16(val) {
return ((val & 0xFF) << 8)
| ((val >> 8) & 0xFF);
}
function extractUncompressedPixels(dataSet, frame, bigEndian)
{ {
var pixelFormat = cornerstoneWADOImageLoader.getPixelFormat(dataSet); var pixelFormat = cornerstoneWADOImageLoader.getPixelFormat(dataSet);
var imageFrame = getImageFrame(dataSet, frame, pixelFormat);
// byte swap 16 bit data if bigEndian
if(bigEndian && (pixelFormat === 2 || pixelFormat === 3)) {
for(var i=0; i < imageFrame.length; i++) {
imageFrame[i] = swap16(imageFrame[i]);
}
}
return imageFrame;
}
function getImageFrame(dataSet, frame, pixelFormat) {
// Note - we may want to sanity check the rows * columns * bitsAllocated * samplesPerPixel against the buffer size
var pixelDataElement = dataSet.elements.x7fe00010; var pixelDataElement = dataSet.elements.x7fe00010;
var height = dataSet.uint16('x00280010'); var height = dataSet.uint16('x00280010');
var width = dataSet.uint16('x00280011'); var width = dataSet.uint16('x00280011');
var samplesPerPixel = dataSet.uint16('x00280002'); var samplesPerPixel = dataSet.uint16('x00280002');
var pixelDataOffset = pixelDataElement.dataOffset; var pixelDataOffset = pixelDataElement.dataOffset;
var numPixels = width * height * samplesPerPixel; var numPixels = width * height * samplesPerPixel;
// Note - we may want to sanity check the rows * columns * bitsAllocated * samplesPerPixel against the buffer size if (!numPixels) {
throw "Sanity check failed when calculating the number of pixels";
}
var frameOffset = 0; var frameOffset = 0;
if(pixelFormat === 1) { if(pixelFormat === 1) {
frameOffset = pixelDataOffset + frame * numPixels; frameOffset = pixelDataOffset + frame * numPixels;
@ -3307,11 +3335,13 @@ var JpegImage = (function jpegImage() {
else if(pixelFormat === 2) { else if(pixelFormat === 2) {
frameOffset = pixelDataOffset + frame * numPixels * 2; frameOffset = pixelDataOffset + frame * numPixels * 2;
return new Uint16Array(dataSet.byteArray.buffer, frameOffset, numPixels); return new Uint16Array(dataSet.byteArray.buffer, frameOffset, numPixels);
return imageFrame;
} }
else if(pixelFormat === 3) { else if(pixelFormat === 3) {
frameOffset = pixelDataOffset + frame * numPixels * 2; frameOffset = pixelDataOffset + frame * numPixels * 2;
return new Int16Array(dataSet.byteArray.buffer, frameOffset, numPixels); return new Int16Array(dataSet.byteArray.buffer, frameOffset, numPixels);
} }
throw "Unknown pixel format";
} }
cornerstoneWADOImageLoader.extractUncompressedPixels = extractUncompressedPixels; cornerstoneWADOImageLoader.extractUncompressedPixels = extractUncompressedPixels;
@ -3373,27 +3403,29 @@ var JpegImage = (function jpegImage() {
"use strict"; "use strict";
function getPixelSpacing(dataSet) function getPixelSpacing(dataSet) {
{
// NOTE - these are not required for all SOP Classes // NOTE - these are not required for all SOP Classes
// so we return them as undefined. We also do not // so we return them as undefined. We also do not
// deal with the complexity associated with projection // deal with the complexity associated with projection
// radiographs here and leave that to a higher layer // radiographs here and leave that to a higher layer
var pixelSpacing = dataSet.string('x00280030'); var pixelSpacing = dataSet.string('x00280030');
if(pixelSpacing && pixelSpacing.length > 0) { if (pixelSpacing && pixelSpacing.length > 0) {
var split = pixelSpacing.split('\\'); var split = pixelSpacing.split('\\');
// Make sure that neither pixel spacing value is 0 or undefined
if (parseFloat(split[0]) && parseFloat(split[1])) {
return { return {
row: parseFloat(split[0]), row: parseFloat(split[0]),
column: parseFloat(split[1]) column: parseFloat(split[1])
}; };
} }
else { }
return { return {
row: undefined, row: undefined,
column: undefined column: undefined
}; };
} }
}
// module exports // module exports
cornerstoneWADOImageLoader.getPixelSpacing = getPixelSpacing; cornerstoneWADOImageLoader.getPixelSpacing = getPixelSpacing;
}(cornerstoneWADOImageLoader)); }(cornerstoneWADOImageLoader));
@ -3411,8 +3443,8 @@ var JpegImage = (function jpegImage() {
}; };
if(dataSet.elements.x00281052 && dataSet.elements.x00281053) { if(dataSet.elements.x00281052 && dataSet.elements.x00281053) {
result.intercept = dataSet.floatString('x00281052'); result.intercept = dataSet.floatString('x00281052') || result.intercept;
result.slope = dataSet.floatString('x00281053'); result.slope = dataSet.floatString('x00281053') || result.slope;
} }
return result; return result;
@ -3480,14 +3512,14 @@ var JpegImage = (function jpegImage() {
}, function(error) { }, function(error) {
deferred.reject(error); deferred.reject(error);
}); });
return deferred; return deferred.promise();
} }
var fileIndex = parseInt(url); var fileIndex = parseInt(url);
var file = cornerstoneWADOImageLoader.fileManager.get(fileIndex); var file = cornerstoneWADOImageLoader.fileManager.get(fileIndex);
if(file === undefined) { if(file === undefined) {
deferred.reject('unknown file index ' + url); deferred.reject('unknown file index ' + url);
return deferred; return deferred.promise();
} }
@ -3508,19 +3540,19 @@ var JpegImage = (function jpegImage() {
}, function(error) { }, function(error) {
deferred.reject(error); deferred.reject(error);
}); });
return deferred; return deferred.promise();
} }
var imagePromise = cornerstoneWADOImageLoader.createImageObject(dataSet, imageId, frame); var imagePromise = cornerstoneWADOImageLoader.createImageObject(dataSet, imageId, frame);
imagePromise.then(function(image) { imagePromise.then(function(image) {
deferred.resolve(image); deferred.resolve(image);
}, function() { }, function(error) {
deferred.reject(); deferred.reject(error);
}); });
}; };
fileReader.readAsArrayBuffer(file); fileReader.readAsArrayBuffer(file);
return deferred; return deferred.promise();
} }
// registery dicomweb and wadouri image loader prefixes // registery dicomweb and wadouri image loader prefixes
@ -3697,7 +3729,7 @@ var JpegImage = (function jpegImage() {
}; };
xhr.send(); xhr.send();
return deferred; return deferred.promise();
}; };
}(cornerstoneWADOImageLoader)); }(cornerstoneWADOImageLoader));
/** /**
@ -3746,7 +3778,7 @@ var JpegImage = (function jpegImage() {
var image = cornerstoneWADOImageLoader.imageManager.get(index); var image = cornerstoneWADOImageLoader.imageManager.get(index);
if(image === undefined) { if(image === undefined) {
deferred.reject('unknown imageId'); deferred.reject('unknown imageId');
return deferred; return deferred.promise();
} }
var mediaType;// = 'image/dicom+jp2'; var mediaType;// = 'image/dicom+jp2';
@ -3781,7 +3813,7 @@ var JpegImage = (function jpegImage() {
deferred.reject(reason); deferred.reject(reason);
}); });
return deferred; return deferred.promise();
} }
// registery dicomweb and wadouri image loader prefixes // registery dicomweb and wadouri image loader prefixes
@ -4044,7 +4076,7 @@ var JpegImage = (function jpegImage() {
} }
catch(err) { catch(err) {
deferred.reject(err); deferred.reject(err);
return deferred; return deferred.promise();
} }
imageDataPromise.then(function(imageData) { imageDataPromise.then(function(imageData) {
@ -4095,7 +4127,8 @@ var JpegImage = (function jpegImage() {
sharedCacheKey: sharedCacheKey sharedCacheKey: sharedCacheKey
}; };
if(image.windowCenter === undefined) { if(image.windowCenter === undefined || isNaN(image.windowCenter) ||
image.windowWidth === undefined || isNaN(image.windowWidth)) {
image.windowWidth = 255; image.windowWidth = 255;
image.windowCenter = 128; image.windowCenter = 128;
} }
@ -4104,7 +4137,7 @@ var JpegImage = (function jpegImage() {
deferred.reject(error); deferred.reject(error);
}); });
return deferred; return deferred.promise();
} }
// module exports // module exports
@ -4171,7 +4204,7 @@ var JpegImage = (function jpegImage() {
bytesPerPixel = getBytesPerPixel(dataSet); bytesPerPixel = getBytesPerPixel(dataSet);
} catch(error) { } catch(error) {
deferred.reject(error); deferred.reject(error);
return deferred; return deferred.promise();
} }
var numPixels = rows * columns; var numPixels = rows * columns;
@ -4188,7 +4221,7 @@ var JpegImage = (function jpegImage() {
} }
catch(err) { catch(err) {
deferred.reject(err); deferred.reject(err);
return deferred; return deferred.promise();
} }
var minMax = cornerstoneWADOImageLoader.getMinMax(storedPixelData); var minMax = cornerstoneWADOImageLoader.getMinMax(storedPixelData);
@ -4241,7 +4274,8 @@ var JpegImage = (function jpegImage() {
// TODO: deal with pixel padding and all of the various issues by setting it to min pixel value (or lower) // TODO: deal with pixel padding and all of the various issues by setting it to min pixel value (or lower)
// TODO: Mask out overlays embedded in pixel data above high bit // TODO: Mask out overlays embedded in pixel data above high bit
if(image.windowCenter === undefined) { if(image.windowCenter === undefined || isNaN(image.windowCenter) ||
image.windowWidth === undefined || isNaN(image.windowWidth)) {
var maxVoi = image.maxPixelValue * image.slope + image.intercept; var maxVoi = image.maxPixelValue * image.slope + image.intercept;
var minVoi = image.minPixelValue * image.slope + image.intercept; var minVoi = image.minPixelValue * image.slope + image.intercept;
image.windowWidth = maxVoi - minVoi; image.windowWidth = maxVoi - minVoi;
@ -4249,7 +4283,7 @@ var JpegImage = (function jpegImage() {
} }
deferred.resolve(image); deferred.resolve(image);
return deferred; return deferred.promise();
} }
// module exports // module exports
@ -4260,7 +4294,7 @@ var JpegImage = (function jpegImage() {
"use strict"; "use strict";
// module exports // module exports
cornerstoneWADOImageLoader.version = '0.8.1'; cornerstoneWADOImageLoader.version = '0.9.0';
}(cornerstoneWADOImageLoader)); }(cornerstoneWADOImageLoader));
(function ($, cornerstone, cornerstoneWADOImageLoader) { (function ($, cornerstone, cornerstoneWADOImageLoader) {
@ -4316,7 +4350,7 @@ var JpegImage = (function jpegImage() {
xhr.send(); xhr.send();
return deferred; return deferred.promise();
} }
cornerstoneWADOImageLoader.internal.xhrRequest = xhrRequest; cornerstoneWADOImageLoader.internal.xhrRequest = xhrRequest;

View File

@ -167,7 +167,7 @@ DIMSE.retrieveInstances = function(studyInstanceUID, seriesInstanceUID, params)
0x0008103E: '', 0x0008103E: '',
0x00200011: '', 0x00200011: '',
0x00080016: '', 0x00080016: '',
0x00080018: '', 0x00080018: '', // sopInstanceUid. This is missing from the results?
0x00200013: '', 0x00200013: '',
0x00280010: '', 0x00280010: '',
0x00280011: '', 0x00280011: '',
@ -181,6 +181,7 @@ DIMSE.retrieveInstances = function(studyInstanceUID, seriesInstanceUID, params)
var instances = []; var instances = [];
result.on('result', function(msg) { result.on('result', function(msg) {
console.log(msg);
instances.push(msg); instances.push(msg);
}); });

View File

@ -17,7 +17,7 @@ Template.studyDateList.helpers({
patientId: currentStudyInBrowser.patientId patientId: currentStudyInBrowser.patientId
}, { }, {
sort: { sort: {
studyDate: 1 studyDate: -1
} }
}); });

View File

@ -10,10 +10,13 @@ Meteor.methods({
throw 'No properly configured server was available over DICOMWeb'; throw 'No properly configured server was available over DICOMWeb';
} }
if (Meteor.settings.dicomWeb && Meteor.settings.defaultServiceType === 'dicomWeb') {
// Get the server data. This is user-defined in the // Get the server data. This is user-defined in the
// config.json files used to run the Meteor server // config.json files used to run the Meteor server
var server = Meteor.settings.dicomWeb.endpoints[0]; var server = Meteor.settings.dicomWeb.endpoints[0];
return Services.WADO.RetrieveMetadata(server, studyInstanceUid); return Services.WADO.RetrieveMetadata(server, studyInstanceUid);
} else if (Meteor.settings.dimse && Meteor.settings.defaultServiceType === 'dimse') {
return Services.DIMSE.RetrieveMetadata(studyInstanceUid);
}
} }
}); });

View File

@ -37,7 +37,7 @@ function resultDataToStudyMetadata(resultData) {
var serverRoot = host + ':' + port; var serverRoot = host + ':' + port;
log.info('INSTANCE'); log.info('INSTANCE');
log.info(instance); //log.info(instance);
var sopInstanceUid = instance[0x00080018]; var sopInstanceUid = instance[0x00080018];
var uri = serverRoot + '/studies/' + studyInstanceUid + '/series/' + seriesInstanceUid + '/instances/' + sopInstanceUid + '/frames/1'; var uri = serverRoot + '/studies/' + studyInstanceUid + '/series/' + seriesInstanceUid + '/instances/' + sopInstanceUid + '/frames/1';

View File

@ -26,6 +26,7 @@ function getSourceImageInstanceUid(instance) {
* @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}} * @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}}
*/ */
function resultDataToStudyMetadata(studyInstanceUid, resultData) { function resultDataToStudyMetadata(studyInstanceUid, resultData) {
console.log('resultDataToStudyMetadata');
var seriesMap = {}; var seriesMap = {};
var seriesList = []; var seriesList = [];
@ -69,7 +70,8 @@ function resultDataToStudyMetadata(studyInstanceUid, resultData) {
var sopInstanceUid = instance[0x00080018]; var sopInstanceUid = instance[0x00080018];
log.info('instance'); log.info('instance');
log.info(instance); //console.log('instance');
//console.log(instance);
var instanceSummary = { var instanceSummary = {
imageType: instance[0x00080008], imageType: instance[0x00080008],
sopClassUid: instance[0x00080016], sopClassUid: instance[0x00080016],
@ -99,12 +101,9 @@ function resultDataToStudyMetadata(studyInstanceUid, resultData) {
frameRate: parseFloat(instance[0x00181063]) frameRate: parseFloat(instance[0x00181063])
}; };
var host = Meteor.settings.dimse.host, // Retrieve the actual data over WADO-URI
port = Meteor.settings.dimse.port; var server = Meteor.settings.dicomWeb.endpoints[0];
instanceSummary.wadouri = server.wadoUriRoot + '?requestType=WADO&studyUID=' + studyInstanceUid + '&seriesUID=' + seriesInstanceUid + '&objectUID=' + sopInstanceUid + "&contentType=application%2Fdicom";
var serverRoot = host + ':' + port;
instanceSummary.wadorsuri = serverRoot + '/studies/' + studyInstanceUid + '/series/' + seriesInstanceUid + '/instances/' + sopInstanceUid + '/frames/1';
series.instances.push(instanceSummary); series.instances.push(instanceSummary);
}); });
@ -156,7 +155,7 @@ Services.DIMSE.RetrieveMetadata = function(studyInstanceUid) {
study.studyInstanceUid = studyInstanceUid; study.studyInstanceUid = studyInstanceUid;
console.log(study); //console.log(study);
console.log(study.seriesList[0].instances[0]); //console.log(study.seriesList[0].instances[0]);
return study; return study;
}; };

View File

@ -6,7 +6,7 @@
"wadoUriRootNOTE" : "either this uri is not correct for wado-uri or wado-uri is not configured on orthanc currently", "wadoUriRootNOTE" : "either this uri is not correct for wado-uri or wado-uri is not configured on orthanc currently",
"wadoUriRoot" : "http://192.168.99.100:8080/dcm4chee-arc/aets/DCM4CHEE/wado", "wadoUriRoot" : "http://192.168.99.100:8080/dcm4chee-arc/aets/DCM4CHEE/wado",
"qidoRoot": "http://192.168.99.100:8080/dcm4chee-arc/aets/DCM4CHEE/rs", "qidoRoot": "http://192.168.99.100:8080/dcm4chee-arc/aets/DCM4CHEE/rs",
"wadoRoot": "http://192.168.99.100:8080/dcm4chee-arc/aets/DCM4CHEE/wado", "wadoRoot": "http://192.168.99.100:8080/dcm4chee-arc/aets/DCM4CHEE/rs/wado/DCM4CHEE",
"qidoSupportsIncludeField": true, "qidoSupportsIncludeField": true,
"imageRendering" : "wadouri", "imageRendering" : "wadouri",
"requestOptions" : { "requestOptions" : {