diff --git a/platform/core/src/classes/MetadataProvider.js b/platform/core/src/classes/MetadataProvider.js index bd3b38870..105ce1847 100644 --- a/platform/core/src/classes/MetadataProvider.js +++ b/platform/core/src/classes/MetadataProvider.js @@ -1,7 +1,7 @@ import * as dcmjs from 'dcmjs'; import queryString from 'query-string'; import dicomParser from 'dicom-parser'; -import { getFallbackTagFromInstance } from '../utils/metadataProvider/metadataProviderFallbackTags'; +import getPixelSpacingInformation from '../utils/metadataProvider/getPixelSpacingInformation'; import fetchPaletteColorLookupTableData from '../utils/metadataProvider/fetchPaletteColorLookupTableData'; import fetchOverlayData from '../utils/metadataProvider/fetchOverlayData'; @@ -161,18 +161,6 @@ class MetadataProvider { return instance[naturalizedTagOrWADOImageLoaderTag]; } - if (options.fallback) { - // Perhaps the tag has fallbacks? - const fallbackTag = getFallbackTagFromInstance( - naturalizedTagOrWADOImageLoaderTag, - instance - ); - - if (fallbackTag) { - return fallbackTag; - } - } - // Maybe its a legacy CornerstoneWADOImageLoader tag then: return this._getCornerstoneWADOImageLoaderTag( naturalizedTagOrWADOImageLoaderTag, @@ -218,10 +206,9 @@ class MetadataProvider { const { ImageOrientationPatient } = instance; // Fallback for DX images. - const PixelSpacing = getFallbackTagFromInstance( - 'PixelSpacing', - instance - ); + // TODO: We should use the rest of the results of this function + // to update the UI somehow + const { PixelSpacing } = getPixelSpacingInformation(instance); let rowPixelSpacing; let columnPixelSpacing; diff --git a/platform/core/src/utils/metadataProvider/getPixelSpacingInformation.js b/platform/core/src/utils/metadataProvider/getPixelSpacingInformation.js new file mode 100644 index 000000000..b8e674109 --- /dev/null +++ b/platform/core/src/utils/metadataProvider/getPixelSpacingInformation.js @@ -0,0 +1,90 @@ +import log from '../../log'; + +export default function getPixelSpacingInformation(instance) { + // See http://gdcm.sourceforge.net/wiki/index.php/Imager_Pixel_Spacing + + // TODO: Add Ultrasound region spacing + // TODO: Add manual calibration + + // TODO: Use ENUMS from dcmjs + const projectionRadiographSOPClassUIDs = [ + '1.2.840.10008.5.1.4.1.1.1', // CR Image Storage + '1.2.840.10008.5.1.4.1.1.1.1', // Digital X-Ray Image Storage – for Presentation + '1.2.840.10008.5.1.4.1.1.1.1.1', // Digital X-Ray Image Storage – for Processing + '1.2.840.10008.5.1.4.1.1.1.2', // Digital Mammography X-Ray Image Storage – for Presentation + '1.2.840.10008.5.1.4.1.1.1.2.1', // Digital Mammography X-Ray Image Storage – for Processing + '1.2.840.10008.5.1.4.1.1.1.3', // Digital Intra – oral X-Ray Image Storage – for Presentation + '1.2.840.10008.5.1.4.1.1.1.3.1', // Digital Intra – oral X-Ray Image Storage – for Processing + '1.2.840.10008.5.1.4.1.1.12.1', // X-Ray Angiographic Image Storage + '1.2.840.10008.5.1.4.1.1.12.1.1', // Enhanced XA Image Storage + '1.2.840.10008.5.1.4.1.1.12.2', // X-Ray Radiofluoroscopic Image Storage + '1.2.840.10008.5.1.4.1.1.12.2.1', // Enhanced XRF Image Storage + '1.2.840.10008.5.1.4.1.1.12.3' // X-Ray Angiographic Bi-plane Image Storage Retired + ]; + + const { PixelSpacing, ImagerPixelSpacing, SOPClassUID, PixelSpacingCalibrationType, PixelSpacingCalibrationDescription, EstimatedRadiographicMagnificationFactor } = instance; + const isProjection = projectionRadiographSOPClassUIDs.includes(SOPClassUID); + + const TYPES = { + NOT_APPLICABLE: 'NOT_APPLICABLE', + UNKNOWN: 'UNKNOWN', + CALIBRATED: 'CALIBRATED', + DETECTOR: 'DETECTOR' + }; + + if (isProjection === false && !ImagerPixelSpacing) { + // If only Pixel Spacing is present, and this is not a projection radiograph, + // we can stop here + return { + PixelSpacing, + type: TYPES.NOT_APPLICABLE, + isProjection + }; + } else if (isProjection && !ImagerPixelSpacing) { + // If only Pixel Spacing is present, and this is a projection radiograph, + // PixelSpacing should be used, but the user should be informed that + // what it means is unknown + return { + PixelSpacing, + type: TYPES.UNKNOWN, + isProjection + }; + } else if (PixelSpacing && ImagerPixelSpacing && PixelSpacing === ImagerPixelSpacing) { + // If Imager Pixel Spacing and Pixel Spacing are present and they have the same values, + // then the user should be informed that the measurements are at the detector plane + return { + PixelSpacing, + type: TYPES.DETECTOR, + isProjection + }; + } else if (PixelSpacing && ImagerPixelSpacing && PixelSpacing !== ImagerPixelSpacing) { + // If Imager Pixel Spacing and Pixel Spacing are present and they have different values, + // then the user should be informed that these are "calibrated" + // (in some unknown manner if Pixel Spacing Calibration Type and/or + // Pixel Spacing Calibration Description are absent) + return { + PixelSpacing, + type: TYPES.CALIBRATED, + isProjection, + PixelSpacingCalibrationType, + PixelSpacingCalibrationDescription + }; + } else if (!PixelSpacing && ImagerPixelSpacing) { + let CorrectedImagerPixelSpacing = ImagerPixelSpacing; + if (EstimatedRadiographicMagnificationFactor) { + // Note that in IHE Mammo profile compliant displays, the value of Imager Pixel Spacing is required to be corrected by + // Estimated Radiographic Magnification Factor and the user informed of that. + // TODO: should this correction be done before all of this logic? + CorrectedImagerPixelSpacing = ImagerPixelSpacing.map(pixelSpacing => pixelSpacing / EstimatedRadiographicMagnificationFactor); + } else { + log.info('EstimatedRadiographicMagnificationFactor was not present. Unable to correct ImagerPixelSpacing.'); + } + + return { + PixelSpacing: CorrectedImagerPixelSpacing, + isProjection, + }; + } + + log.info('Unknown combination of PixelSpacing and ImagerPixelSpacing identified. Unable to determine spacing.'); +} diff --git a/platform/core/src/utils/metadataProvider/metadataProviderFallbackTags.js b/platform/core/src/utils/metadataProvider/metadataProviderFallbackTags.js deleted file mode 100644 index f75faf3f3..000000000 --- a/platform/core/src/utils/metadataProvider/metadataProviderFallbackTags.js +++ /dev/null @@ -1,27 +0,0 @@ -import log from '../../log'; - -function getFallbackTagFromInstance(tag, instance) { - if (instance[tag]) { - return instance[tag]; - } - - const fallbackTags = fallbackTagsMap[tag]; - - if (fallbackTags) { - for (let i = 0; i < fallbackTags.length; i++) { - const fallbackTag = fallbackTags[i]; - - if (instance[fallbackTag]) { - log.info(`metadata provider fallback tag ${tag} to ${fallbackTag}`); - - return instance[fallbackTag]; - } - } - } -} - -const fallbackTagsMap = { - PixelSpacing: ['ImagerPixelSpacing'], -}; - -export { fallbackTagsMap, getFallbackTagFromInstance };