From 6003f67865d092d9c58b96dbf2fcd9d2a0393cb4 Mon Sep 17 00:00:00 2001 From: "Emanuel F. Oliveira" Date: Thu, 19 Jan 2017 02:24:33 -0200 Subject: [PATCH] Fixed issue on ordering of display sets in OHIF Viewers + Fixed issue with tag to property name translation on OHIFInstanceMetadata class. --- .../client/OHIFInstanceMetadata.js | 35 +++++++++++++------ .../lib/classes/metadata/InstanceMetadata.js | 19 +++++----- .../client/lib/createStacks.js | 12 +++---- .../client/lib/dicomTagDescriptions.js | 21 +++++++++-- 4 files changed, 58 insertions(+), 29 deletions(-) diff --git a/Packages/ohif-metadata/client/OHIFInstanceMetadata.js b/Packages/ohif-metadata/client/OHIFInstanceMetadata.js index 7996f488a..1d5ae9e0b 100644 --- a/Packages/ohif-metadata/client/OHIFInstanceMetadata.js +++ b/Packages/ohif-metadata/client/OHIFInstanceMetadata.js @@ -9,6 +9,7 @@ export class OHIFInstanceMetadata extends InstanceMetadata { */ constructor(data) { super(data); + this._cache = Object.create(null); // Object with null prototype for fast and safe lookups... this.init(); } @@ -19,13 +20,24 @@ export class OHIFInstanceMetadata extends InstanceMetadata { } // Override - getRawValue(tagOrProperty, defaultValue) { - const propertyName = OHIFInstanceMetadata.getPropertyName(tagOrProperty); + getRawValue(tagOrProperty, defaultValue, bypassCache) { + // check if this property has been cached... + if (tagOrProperty in this._cache && bypassCache !== true) { + return this._cache[tagOrProperty]; + } + + const propertyName = OHIFInstanceMetadata.getPropertyName(tagOrProperty); const data = this.getData(); const rawValue = data[propertyName]; - return rawValue !== void 0 ? rawValue : defaultValue; + if (rawValue !== void 0) { + // if rawValue value is not undefined, cache result... + this._cache[tagOrProperty] = rawValue; + return rawValue; + } + + return defaultValue; } // Override @@ -40,19 +52,20 @@ export class OHIFInstanceMetadata extends InstanceMetadata { /** * Static methods */ - + + // @TODO: The current mapping of standard DICOM property names to local property names is not optimal. + // The inconsistency in property naming makes this function increasingly complex. + // A possible solution to improve this would be adapt retriveMetadata names to use DICOM standard names as in dicomTagDescriptions.js static getPropertyName(tagOrProperty) { + let propertyName; const tagInfo = InstanceMetadata.getTagInfo(tagOrProperty); - if(tagInfo.propertyName === null) { - return; + if (tagInfo.propertyName !== null) { + // This function tries to translate standard DICOM property names into local naming convention. + propertyName = tagInfo.propertyName.replace(/^SOP/, 'sop').replace(/UID$/, 'Uid'); + propertyName = propertyName.charAt(0).toLowerCase() + propertyName.substr(1); } - let propertyName = tagInfo.propertyName.charAt(0).toLowerCase() + tagInfo.propertyName.substr(1); - // TODO: Improve this: change retriveMetadata to use dicom standard names (see dicomTagDescriptions.js) - propertyName = propertyName.replace(/^sop/, 'SOP'); - propertyName = propertyName.replace(/uid$/i, 'UID'); - return propertyName; } } diff --git a/Packages/ohif-viewerbase/client/lib/classes/metadata/InstanceMetadata.js b/Packages/ohif-viewerbase/client/lib/classes/metadata/InstanceMetadata.js index ef18ffc4a..6cf7bd1a3 100644 --- a/Packages/ohif-viewerbase/client/lib/classes/metadata/InstanceMetadata.js +++ b/Packages/ohif-viewerbase/client/lib/classes/metadata/InstanceMetadata.js @@ -126,22 +126,25 @@ export class InstanceMetadata extends Metadata { if (typeof tagOrProperty === NUMBER) { // if it's a number, build an hexadecimal representation... tagName = 'x' + ('00000000' + tagOrProperty.toString(16)).substr(-8); - } else if (typeof tagOrProperty === STRING && REGEX_TAG.test(tagOrProperty)) { - tagName = tagOrProperty; - } else { - // use it as a property name otherwise... - propertyName = tagOrProperty; + } else if (typeof tagOrProperty === STRING) { + if (REGEX_TAG.test(tagOrProperty)) { + tagName = tagOrProperty; + } else { + propertyName = tagOrProperty; + } } - // It's a property - if (tagName === null) { + if (propertyName !== null) { + // try to figure out the "tagName" using the provided "propertyName"... for (let tag in dicomTagDescriptions) { + // No need to check for "hasOwnProperty" here since dicomTagDescriptions is an object with no prototype... if (dicomTagDescriptions[tag] === propertyName) { tagName = tag; break; } } - } else if (propertyName === null) { + } else if (tagName !== null) { + // try to figure out the "propertyName" using the provided "tagName"... propertyName = dicomTagDescriptions[tagName] || null; } diff --git a/Packages/ohif-viewerbase/client/lib/createStacks.js b/Packages/ohif-viewerbase/client/lib/createStacks.js index f13e9d78e..e881fa66a 100644 --- a/Packages/ohif-viewerbase/client/lib/createStacks.js +++ b/Packages/ohif-viewerbase/client/lib/createStacks.js @@ -2,7 +2,8 @@ import { ImageSet } from './classes/ImageSet'; import { isImage } from './isImage'; const isMultiFrame = instance => { - return instance.getRawValue('NumberOfFrames') > 1; + // NumberOfFrames (0028,0008) + return instance.getRawValue('x00280008') > 1; }; const makeDisplaySet = (series, instances) => { @@ -25,13 +26,8 @@ const makeDisplaySet = (series, instances) => { // Sort the images in this series imageSet.sortBy((a, b) => { - // Sort by instance Number - const aInstanceNumber = a.getRawValue('x00200013'); - const bInstanceNumber = b.getRawValue('x00200013'); - if (a.instanceNumber && b.instanceNumber && - a.instanceNumber !== b.instanceNumber) { - return a.instanceNumber - b.instanceNumber; - } + // Sort by InstanceNumber (0020,0013) + return (parseInt(a.getRawValue('x00200013', 0)) || 0) - (parseInt(b.getRawValue('x00200013', 0)) || 0); }); // Include the first image instance number (after sorted) diff --git a/Packages/ohif-viewerbase/client/lib/dicomTagDescriptions.js b/Packages/ohif-viewerbase/client/lib/dicomTagDescriptions.js index 4e6e13925..b4c43783f 100644 --- a/Packages/ohif-viewerbase/client/lib/dicomTagDescriptions.js +++ b/Packages/ohif-viewerbase/client/lib/dicomTagDescriptions.js @@ -1,4 +1,6 @@ -export const dicomTagDescriptions = { + +const dicomTagDescriptions = Object.create(null); // Object with null prototype for fast and safe lookups... +let _dicomTagDescriptions = { x00020000: 'FileMetaInfoGroupLength', x00020001: 'FileMetaInfoVersion', x00020002: 'MediaStorageSOPClassUID', @@ -3145,4 +3147,19 @@ export const dicomTagDescriptions = { xfffee000: 'StartOfItem', xfffee00d: 'EndOfItems', xfffee0dd: 'EndOfSequence' -}; \ No newline at end of file +}; + +// Safely copy tag descriptions to exported objects... +(function(_dicomTagDescriptions) { + const _hasOwn = Object.prototype.hasOwnProperty; + for (let tag in _dicomTagDescriptions) { + if (_hasOwn.call(_dicomTagDescriptions, tag)) { + dicomTagDescriptions[tag] = _dicomTagDescriptions[tag]; + } + } +}(_dicomTagDescriptions)); + +// Discard original object... +_dicomTagDescriptions = null; + +export { dicomTagDescriptions };