Re IDC #2762: fix thumbnail series type for unsupported SOPClassUID (#2770)

This commit is contained in:
Davide Punzo 2022-04-06 17:10:00 +02:00 committed by GitHub
parent 64385485b6
commit cedeb756c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 227 additions and 11 deletions

View File

@ -59,7 +59,7 @@ const DicomTagBrowser = ({ displaySets, displaySetInstanceUID }) => {
let metadata;
const isImageStack =
activeDisplaySet instanceof ImageSet &&
activeDisplaySet.isModalitySupported === true;
activeDisplaySet.isSOPClassUIDSupported === true;
let instanceList;

View File

@ -3,12 +3,12 @@ import DICOMWeb from './../../DICOMWeb';
import ImageSet from './../ImageSet';
import { InstanceMetadata } from './InstanceMetadata';
import { Metadata } from './Metadata';
import OHIFError from '../OHIFError';
import { SeriesMetadata } from './SeriesMetadata';
// - createStacks
import { api } from 'dicomweb-client';
// - createStacks
import { isImage } from '../../utils/isImage';
import { naturalizeSOPClassUID } from '../../utils/naturalizeSOPClassUID';
import {
isDisplaySetReconstructable,
isSpacingUniform,
@ -169,8 +169,12 @@ class StudyMetadata extends Metadata {
!isImage(instance.getTagValue('SOPClassUID')) &&
!instance.getTagValue('Rows')
) {
// we set an empty display and we add a isModalitySupported variable to
// print a warning that the modality is not supported in the thumbnail.
// we set an empty display and we add a isSOPClassUIDSupported variable to
// print a warning that the series is not supported in the thumbnail.
// SOPClassUIDNaturalized is human readable name, since for non image series,
// we could have a mismatch between the SOPClassUID and the Modality.
// For example, in the Parametric map IOD Modality is expected to match
// the value for the series used to generate Parametric map, and there is no "PM" modality.
const displaySet = new ImageSet([]);
const seriesData = series.getData();
displaySet.setAttributes({
@ -188,7 +192,10 @@ class StudyMetadata extends Metadata {
InstanceNumber: instance.getTagValue('InstanceNumber'), // Include the instance number
AcquisitionDatetime: instance.getTagValue('AcquisitionDateTime'), // Include the acquisition datetime
isReconstructable: false,
isModalitySupported: false,
isSOPClassUIDSupported: false,
SOPClassUIDNaturalized: naturalizeSOPClassUID(
instance.getTagValue('SOPClassUID')
),
metadata: instance.getData().metadata,
});
@ -923,7 +930,7 @@ const makeDisplaySet = (series, instances) => {
: displayReconstructableInfo.reconstructionIssues;
}
imageSet.isModalitySupported = true;
imageSet.isSOPClassUIDSupported = true;
return imageSet;
};

View File

@ -0,0 +1,200 @@
import { sopClassDictionary } from './sopClassDictionary';
import { isImage } from './isImage';
/**
* Naturalize SOP Class UID which do not have image data
* @param {string} SOPClassUID - SOP Class UID to be converted
* @returns {string} - human readable name
*/
export const naturalizeSOPClassUID = SOPClassUID => {
let naturalizedName = '';
if (!SOPClassUID) return naturalizedName;
if (!isImage) return naturalizedName;
if (sopClassDictionary.MRSpectroscopyStorage === SOPClassUID) {
naturalizedName = 'MRSpectroscopy';
} else if (sopClassDictionary.EnhancedUSVolumeStorage === SOPClassUID) {
naturalizedName = 'EnhancedUSVolume';
} else if (sopClassDictionary.Sop12LeadECGWaveformStorage === SOPClassUID) {
naturalizedName = 'Sop12LeadECGWaveform';
} else if (sopClassDictionary.GeneralECGWaveformStorage === SOPClassUID) {
naturalizedName = 'GeneralECGWaveform';
} else if (sopClassDictionary.AmbulatoryECGWaveformStorage === SOPClassUID) {
naturalizedName = 'AECAmbulatoryECGWaveformGW';
} else if (sopClassDictionary.HemodynamicWaveformStorage === SOPClassUID) {
naturalizedName = 'HemodynamicWaveform';
} else if (
sopClassDictionary.CardiacElectrophysiologyWaveformStorage === SOPClassUID
) {
naturalizedName = 'CardiacElectrophysiologyWaveform';
} else if (
sopClassDictionary.BasicVoiceAudioWaveformStorage === SOPClassUID
) {
naturalizedName = 'BasicVoiceAudioWaveform';
} else if (sopClassDictionary.GeneralAudioWaveformStorage === SOPClassUID) {
naturalizedName = 'GGeneralAudioWaveformAW';
} else if (sopClassDictionary.ArterialPulseWaveformStorage === SOPClassUID) {
naturalizedName = 'APArterialPulseWaveformW';
} else if (sopClassDictionary.RespiratoryWaveformStorage === SOPClassUID) {
naturalizedName = 'RespiratoryWaveform';
} else if (
sopClassDictionary.GrayscaleSoftcopyPresentationStateStorage === SOPClassUID
) {
naturalizedName = 'GrayscaleSoftcopyPresentationState';
} else if (
sopClassDictionary.ColorSoftcopyPresentationStateStorage === SOPClassUID
) {
naturalizedName = 'ColorSoftcopyPresentationState';
} else if (
sopClassDictionary.PseudoColorSoftcopyPresentationStateStorage ===
SOPClassUID
) {
naturalizedName = 'PseudoColorSoftcopyPresentationState';
} else if (
sopClassDictionary.BlendingSoftcopyPresentationStateStorage === SOPClassUID
) {
naturalizedName = 'BlendingSoftcopyPresentationState';
} else if (
sopClassDictionary.XAXRFGrayscaleSoftcopyPresentationStateStorage ===
SOPClassUID
) {
naturalizedName = 'XAXRFGrayscaleSoftcopyPresentationState';
} else if (sopClassDictionary.RawDataStorage === SOPClassUID) {
naturalizedName = 'RawData';
} else if (sopClassDictionary.SpatialRegistrationStorage === SOPClassUID) {
naturalizedName = 'SpatialRegistration';
} else if (sopClassDictionary.SpatialFiducialsStorage === SOPClassUID) {
naturalizedName = 'SpatialFiducials';
} else if (
sopClassDictionary.DeformableSpatialRegistrationStorage === SOPClassUID
) {
naturalizedName = 'DeformableSpatialRegistration';
} else if (sopClassDictionary.SegmentationStorage === SOPClassUID) {
naturalizedName = 'SEG';
} else if (sopClassDictionary.SurfaceSegmentationStorage === SOPClassUID) {
naturalizedName = 'SurfaceSEG';
} else if (sopClassDictionary.RealWorldValueMappingStorage === SOPClassUID) {
naturalizedName = 'RealWorldValueMapping';
} else if (sopClassDictionary.SurfaceScanMeshStorage === SOPClassUID) {
naturalizedName = 'SurfaceScanMesh';
} else if (sopClassDictionary.SurfaceScanPointCloudStorage === SOPClassUID) {
naturalizedName = 'SurfaceScanPointCloud';
} else if (
sopClassDictionary.StereometricRelationshipStorage === SOPClassUID
) {
naturalizedName = 'StereometricRelationship';
} else if (sopClassDictionary.LensometryMeasurementsStorage === SOPClassUID) {
naturalizedName = 'LensometryMeasurements';
} else if (
sopClassDictionary.AutorefractionMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'AutorefractionMeasurements';
} else if (
sopClassDictionary.KeratometryMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'KeratometryMeasurements';
} else if (
sopClassDictionary.SubjectiveRefractionMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'SubjectiveRefractionMeasurements';
} else if (
sopClassDictionary.VisualAcuityMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'VisualAcuityMeasurements';
} else if (
sopClassDictionary.SpectaclePrescriptionReportStorage === SOPClassUID
) {
naturalizedName = 'SpectaclePrescriptionReport';
} else if (
sopClassDictionary.OphthalmicAxialMeasurementsStorage === SOPClassUID
) {
naturalizedName = 'OphthalmicAxialMeasurements';
} else if (
sopClassDictionary.IntraocularLensCalculationsStorage === SOPClassUID
) {
naturalizedName = 'IntraocularLensCalculations';
} else if (
sopClassDictionary.MacularGridThicknessandVolumeReport === SOPClassUID
) {
naturalizedName = 'MacularGridThicknessandVolume';
} else if (
sopClassDictionary.OphthalmicVisualFieldStaticPerimetryMeasurementsStorage ===
SOPClassUID
) {
naturalizedName = 'OphthalmicVisualFieldStaticPerimetryMeasurements';
} else if (sopClassDictionary.OphthalmicThicknessMapStorage === SOPClassUID) {
naturalizedName = 'OphthalmicThicknessMap';
} else if (sopClassDictionary.CornealTopographyMapStorage === SOPClassUID) {
naturalizedName = 'CornealTopographyMap';
} else if (sopClassDictionary.BasicTextSR === SOPClassUID) {
naturalizedName = 'BasicTextSR';
} else if (sopClassDictionary.EnhancedSR === SOPClassUID) {
naturalizedName = 'EnhancedSR';
} else if (sopClassDictionary.ComprehensiveSR === SOPClassUID) {
naturalizedName = 'ComprehensiveSR';
} else if (sopClassDictionary.Comprehensive3DSR === SOPClassUID) {
naturalizedName = 'Comprehensive3DSR';
} else if (sopClassDictionary.ProcedureLog === SOPClassUID) {
naturalizedName = 'ProcedureLog';
} else if (sopClassDictionary.MammographyCADSR === SOPClassUID) {
naturalizedName = 'MammographyCADSR';
} else if (sopClassDictionary.KeyObjectSelection === SOPClassUID) {
naturalizedName = 'KeyObject';
} else if (sopClassDictionary.ChestCADSR === SOPClassUID) {
naturalizedName = 'ChestCADSR';
} else if (sopClassDictionary.XRayRadiationDoseSR === SOPClassUID) {
naturalizedName = 'XRayRadiationDoseSR';
} else if (
sopClassDictionary.RadiopharmaceuticalRadiationDoseSR === SOPClassUID
) {
naturalizedName = 'RadiopharmaceuticalRadiationDoseSR';
} else if (sopClassDictionary.ColonCADSR === SOPClassUID) {
naturalizedName = 'ColonCADSR';
} else if (
sopClassDictionary.ImplantationPlanSRDocumentStorage === SOPClassUID
) {
naturalizedName = 'ImplantationPlanSRDocument';
} else if (sopClassDictionary.EncapsulatedPDFStorage === SOPClassUID) {
naturalizedName = 'EncapsulatedPDF';
} else if (sopClassDictionary.EncapsulatedCDAStorage === SOPClassUID) {
naturalizedName = 'EncapsulatedCDA';
} else if (sopClassDictionary.BasicStructuredDisplayStorage === SOPClassUID) {
naturalizedName = 'BasicStructuredDisplay';
} else if (sopClassDictionary.RTDoseStorage === SOPClassUID) {
naturalizedName = 'RTDose';
} else if (sopClassDictionary.RTStructureSetStorage === SOPClassUID) {
naturalizedName = 'RTStructureSet';
} else if (sopClassDictionary.RTBeamsTreatmentRecordStorage === SOPClassUID) {
naturalizedName = 'RTBeamsTreatmentRecord';
} else if (sopClassDictionary.RTPlanStorage === SOPClassUID) {
naturalizedName = 'RTPlan';
} else if (
sopClassDictionary.RTBrachyTreatmentRecordStorage === SOPClassUID
) {
naturalizedName = 'RTBrachyTreatmentRecord';
} else if (
sopClassDictionary.RTTreatmentSummaryRecordStorage === SOPClassUID
) {
naturalizedName = 'RTTreatmentSummaryRecord';
} else if (sopClassDictionary.RTIonPlanStorage === SOPClassUID) {
naturalizedName = 'RTIonPlan';
} else if (
sopClassDictionary.RTIonBeamsTreatmentRecordStorage === SOPClassUID
) {
naturalizedName = 'RTIonBeamsTreatmentRecord';
} else if (
sopClassDictionary.RTBeamsDeliveryInstructionStorage === SOPClassUID
) {
naturalizedName = 'RTBeamsDeliveryInstruction';
} else if (sopClassDictionary.GenericImplantTemplateStorage === SOPClassUID) {
naturalizedName = 'GenericImplantTemplate';
} else if (
sopClassDictionary.ImplantAssemblyTemplateStorage === SOPClassUID
) {
naturalizedName = 'ImplantAssemblyTemplate';
} else if (sopClassDictionary.ImplantTemplateGroupStorage === SOPClassUID) {
naturalizedName = 'ImplantTemplateGroup';
}
return naturalizedName;
};

View File

@ -25,7 +25,8 @@
box-shadow: inset 0 0 0 1px var(--ui-border-color-dark);
border: 2px solid transparent;
border-radius: 12px;
height: 135px;
min-height: 135px;
max-height: 250px;
margin: 0 auto;
padding: 5px;
position: relative;
@ -36,6 +37,11 @@
h1
text-align: center
color: var(--text-primary-color);
max-width: 200px;
max-height: 250px;
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
.series-details
display: flex;

View File

@ -30,6 +30,7 @@ window.config = {
},
],
},
// Extensions should be able to suggest default values for these?
// Or we can require that these be explicitly set
hotkeys: [

View File

@ -79,7 +79,7 @@ const mapDispatchToProps = (dispatch, ownProps) => {
});
}
if (displaySet.isModalitySupported === false) {
if (displaySet.isSOPClassUIDSupported === false) {
const error = new Error('Modality not supported');
const message = 'Modality not supported';
LoggerService.error({ error, message });

View File

@ -563,8 +563,8 @@ const _checkForSeriesInconsistencesWarnings = async function(displaySet) {
);
}
if (displaySet.isModalitySupported === false) {
inconsistencyWarnings.push('The datasets modality is not supported.');
if (displaySet.isSOPClassUIDSupported === false) {
inconsistencyWarnings.push('The datasets is not supported.');
}
displaySet.inconsistencyWarnings = inconsistencyWarnings;
} else {
@ -668,6 +668,8 @@ const _mapStudiesToThumbnails = function(studies, activeDisplaySetInstanceUID) {
} else if (displaySet.images && displaySet.images.length) {
const imageIndex = Math.floor(displaySet.images.length / 2);
imageId = displaySet.images[imageIndex].getImageId();
} else if (displaySet.isSOPClassUIDSupported === false) {
altImageText = displaySet.SOPClassUIDNaturalized;
} else {
altImageText = displaySet.Modality ? displaySet.Modality : 'UN';
}

View File

@ -190,7 +190,7 @@ class ViewerMain extends Component {
}
}
if (displaySet.isModalitySupported === false) {
if (displaySet.isSOPClassUIDSupported === false) {
const error = new Error('Modality not supported');
const message = 'Modality not supported';
LoggerService.error({ error, message });