diff --git a/Packages/dicomweb/package.js b/Packages/dicomweb/package.js index e59ea1f99..9c899d670 100644 --- a/Packages/dicomweb/package.js +++ b/Packages/dicomweb/package.js @@ -9,6 +9,7 @@ Package.onUse(function(api) { // DICOMWeb API functions api.addFiles('server/namespace.js', 'server'); + api.addFiles('server/getAttribute.js', 'server'); api.addFiles('server/getJSON.js', 'server'); api.addFiles('server/getName.js', 'server'); api.addFiles('server/getNumber.js', 'server'); diff --git a/Packages/dicomweb/server/getAttribute.js b/Packages/dicomweb/server/getAttribute.js new file mode 100644 index 000000000..bcb2a96e4 --- /dev/null +++ b/Packages/dicomweb/server/getAttribute.js @@ -0,0 +1,44 @@ +/** + * Returns the specified element as a dicom attribute group/element. + * + * @param element - The group/element of the element (e.g. '00280009') + * @param [defaultValue] - The value to return if the element is not present + * @returns {*} + */ +DICOMWeb.getAttribute = function(element, defaultValue) { + if (!element) { + return defaultValue; + } + // Value is not present if the attribute has a zero length value + if (!element.Value) { + return defaultValue; + } + // Sanity check to make sure we have at least one entry in the array. + if (!element.Value.length) { + return defaultValue; + } + + return convertToInt(element.Value); +}; + +function convertToInt(input) { + function padFour(input) { + var l = input.length; + + if (l == 0) return '0000'; + if (l == 1) return '000' + input; + if (l == 2) return '00' + input; + if (l == 3) return '0' + input; + + return input; + } + + var output = ''; + for (var i = 0; i < input.length; i++) { + for (var j = 0; j < input[i].length; j++) { + output += padFour(input[i].charCodeAt(j).toString(16)); + } + } + + return parseInt(output, 16); +} diff --git a/Packages/dimseservice/server/DIMSE.js b/Packages/dimseservice/server/DIMSE.js index b5d6c890a..d33077e75 100755 --- a/Packages/dimseservice/server/DIMSE.js +++ b/Packages/dimseservice/server/DIMSE.js @@ -39,7 +39,9 @@ var getInstanceRetrievalParams = function(studyInstanceUID, seriesInstanceUID) { 0x00280004: '', // photometricInterpretation 0x0008002A: '', // acquisitionDatetime 0x00280008: '', // numFrames + 0x00280009: '', // frameIncrementPointer 0x00181063: '', // frameTime + 0x00181065: '', // frameTimeVector 0x00281052: '', // rescaleIntercept 0x00281053: '', // rescaleSlope 0x00280002: '', // samplesPerPixel diff --git a/Packages/dimseservice/server/Data.js b/Packages/dimseservice/server/Data.js index e19dee3a2..a84b088e0 100755 --- a/Packages/dimseservice/server/Data.js +++ b/Packages/dimseservice/server/Data.js @@ -210,11 +210,14 @@ util.inherits(AttributeTag, ValueRepresentation); AttributeTag.prototype.readBytes = function(stream, length) { var group = stream.read(C.TYPE_UINT16), - element = stream.read(C.TYPE_UINT16); + element = stream.read(C.TYPE_UINT16); return tagFromNumbers(group, element); }; AttributeTag.prototype.getFields = function(value) { + if (!value) + return AttributeTag.super_.prototype.getFields.call(this, [new StringField("")]); + return AttributeTag.super_.prototype.getFields.call(this, [new UInt16Field(value.group()), new UInt16Field(value.element())]); }; diff --git a/Packages/worklist/package.js b/Packages/worklist/package.js index d142dc37c..c511e408d 100644 --- a/Packages/worklist/package.js +++ b/Packages/worklist/package.js @@ -121,6 +121,7 @@ Package.onUse(function (api) { api.addFiles('server/servers.js', 'server'); api.addFiles('server/lib/remoteGetValue.js', 'server'); api.addFiles('server/lib/encodeQueryData.js', 'server'); + api.addFiles('server/lib/parseFloatArray.js', 'server'); api.addFiles('server/methods/getStudyMetadata.js', 'server'); api.addFiles('server/methods/importStudies.js', 'server'); diff --git a/Packages/worklist/server/lib/parseFloatArray.js b/Packages/worklist/server/lib/parseFloatArray.js new file mode 100644 index 000000000..22641318e --- /dev/null +++ b/Packages/worklist/server/lib/parseFloatArray.js @@ -0,0 +1,14 @@ +export const parseFloatArray = function(obj) { + var result = []; + + if (!obj) { + return result; + } + + var objs = obj.split("\\"); + for (var i = 0; i < objs.length; i++) { + result.push(parseFloat(objs[i])); + } + + return result; +}; diff --git a/Packages/worklist/server/services/dimse/retrieveMetadata.js b/Packages/worklist/server/services/dimse/retrieveMetadata.js index e4d5bc202..1b4c37df6 100755 --- a/Packages/worklist/server/services/dimse/retrieveMetadata.js +++ b/Packages/worklist/server/services/dimse/retrieveMetadata.js @@ -1,3 +1,5 @@ +import { parseFloatArray } from '../../lib/parseFloatArray'; + /** * Parses the SourceImageSequence, if it exists, in order * to return a ReferenceSOPInstanceUID. The ReferenceSOPInstanceUID @@ -16,6 +18,21 @@ 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 @@ -102,7 +119,9 @@ function resultDataToStudyMetadata(studyInstanceUid, resultData) { viewPosition: instance[0x00185101], acquisitionDatetime: instance[0x0008002A], numFrames: parseFloat(instance[0x00280008]), + frameIncrementPointer: getValue(instance[0x00280009]), frameTime: parseFloat(instance[0x00181063]), + frameTimeVector: parseFloatArray(instance[0x00181065]), lossyImageCompression: instance[0x00282110], derivationDescription: instance[0x00282111], lossyImageCompressionRatio: instance[0x00282112], diff --git a/Packages/worklist/server/services/remote/retrieveMetadata.js b/Packages/worklist/server/services/remote/retrieveMetadata.js index 278cd7d3b..949703936 100755 --- a/Packages/worklist/server/services/remote/retrieveMetadata.js +++ b/Packages/worklist/server/services/remote/retrieveMetadata.js @@ -1,4 +1,5 @@ import { remoteGetValue } from '../../lib/remoteGetValue'; +import { parseFloatArray } from '../../lib/parseFloatArray'; /** * Parses the SourceImageSequence, if it exists, in order @@ -97,7 +98,9 @@ function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { viewPosition: remoteGetValue(instance['0018,5101']), acquisitionDatetime: remoteGetValue(instance['0008,002A']), numFrames: parseFloat(remoteGetValue(instance['0028,0008'])), - frameTime: parseFloat(remoteGetValue(instance['0018,1063'])) + frameIncrementPointer: remoteGetValue(instance['0028,0009']), + frameTime: parseFloat(remoteGetValue(instance['0018,1063'])), + frameTimeVector: parseFloatArray(remoteGetValue(instance['0018,1065'])) }; var iid = instance['xxxx,0001'].Value; diff --git a/Packages/worklist/server/services/wado/retrieveMetadata.js b/Packages/worklist/server/services/wado/retrieveMetadata.js index 466ca9a5b..528a0fcb8 100644 --- a/Packages/worklist/server/services/wado/retrieveMetadata.js +++ b/Packages/worklist/server/services/wado/retrieveMetadata.js @@ -1,3 +1,5 @@ +import { parseFloatArray } from '../../lib/parseFloatArray'; + /** * Creates a URL for a WADO search * @@ -108,7 +110,9 @@ function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { viewPosition: DICOMWeb.getString(instance['00185101']), acquisitionDatetime: DICOMWeb.getString(instance['0008002A']), numFrames: DICOMWeb.getNumber(instance['00280008']), + frameIncrementPointer: DICOMWeb.getAttribute(instance['00280009']), frameTime: DICOMWeb.getNumber(instance['00181063']), + frameTimeVector: parseFloatArray(DICOMWeb.getString(instance['00181065'])), sliceThickness: DICOMWeb.getNumber(instance['00180050']), lossyImageCompression: DICOMWeb.getString(instance['00282110']), derivationDescription: DICOMWeb.getString(instance['00282111']),