601 lines
20 KiB
TypeScript
601 lines
20 KiB
TypeScript
import queryString from 'query-string';
|
|
import dicomParser from 'dicom-parser';
|
|
import { imageIdToURI } from '../utils';
|
|
import getPixelSpacingInformation from '../utils/metadataProvider/getPixelSpacingInformation';
|
|
import DicomMetadataStore from '../services/DicomMetadataStore';
|
|
import fetchPaletteColorLookupTableData from '../utils/metadataProvider/fetchPaletteColorLookupTableData';
|
|
import toNumber from '../utils/toNumber';
|
|
import combineFrameInstance from '../utils/combineFrameInstance';
|
|
|
|
class MetadataProvider {
|
|
constructor() {
|
|
// Define the main "metadataLookup" private property as an immutable property.
|
|
Object.defineProperty(this, 'studies', {
|
|
configurable: false,
|
|
enumerable: false,
|
|
writable: false,
|
|
value: new Map(),
|
|
});
|
|
Object.defineProperty(this, 'imageURIToUIDs', {
|
|
configurable: false,
|
|
enumerable: false,
|
|
writable: false,
|
|
value: new Map(),
|
|
});
|
|
// Can be used to store custom metadata for a specific type.
|
|
// For instance, the scaling metadata for PET can be stored here
|
|
// as type "scalingModule"
|
|
//
|
|
Object.defineProperty(this, 'customMetadata', {
|
|
configurable: false,
|
|
enumerable: false,
|
|
writable: false,
|
|
value: new Map(),
|
|
});
|
|
}
|
|
|
|
addImageIdToUIDs(imageId, uids) {
|
|
// This method is a fallback for when you don't have WADO-URI or WADO-RS.
|
|
// You can add instances fetched by any method by calling addInstance, and hook an imageId to point at it here.
|
|
// An example would be dicom hosted at some random site.
|
|
const imageURI = imageIdToURI(imageId);
|
|
this.imageURIToUIDs.set(imageURI, uids);
|
|
}
|
|
|
|
addCustomMetadata(imageId, type, metadata) {
|
|
const imageURI = imageIdToURI(imageId);
|
|
if (!this.customMetadata.has(type)) {
|
|
this.customMetadata.set(type, {});
|
|
}
|
|
|
|
this.customMetadata.get(type)[imageURI] = metadata;
|
|
}
|
|
|
|
_getInstance(imageId) {
|
|
const uids = this.getUIDsFromImageID(imageId);
|
|
|
|
if (!uids) {
|
|
return;
|
|
}
|
|
|
|
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID, frameNumber } = uids;
|
|
|
|
const instance = DicomMetadataStore.getInstance(
|
|
StudyInstanceUID,
|
|
SeriesInstanceUID,
|
|
SOPInstanceUID
|
|
);
|
|
|
|
if (!instance) {
|
|
return;
|
|
}
|
|
|
|
return (frameNumber && combineFrameInstance(frameNumber, instance)) || instance;
|
|
}
|
|
|
|
get(query, imageId, options = { fallback: false }) {
|
|
if (Array.isArray(imageId)) {
|
|
return;
|
|
}
|
|
const instance = this._getInstance(imageId);
|
|
|
|
if (query === INSTANCE) {
|
|
return instance;
|
|
}
|
|
|
|
// check inside custom metadata
|
|
if (this.customMetadata.has(query)) {
|
|
const customMetadata = this.customMetadata.get(query);
|
|
const imageURI = imageIdToURI(imageId);
|
|
if (customMetadata[imageURI]) {
|
|
return customMetadata[imageURI];
|
|
}
|
|
}
|
|
|
|
return this.getTagFromInstance(query, instance, options);
|
|
}
|
|
|
|
getTag(query, imageId, options) {
|
|
return this.get(query, imageId, options);
|
|
}
|
|
|
|
getInstance(imageId) {
|
|
return this.get(INSTANCE, imageId);
|
|
}
|
|
|
|
getTagFromInstance(naturalizedTagOrWADOImageLoaderTag, instance, options = { fallback: false }) {
|
|
if (!instance) {
|
|
return;
|
|
}
|
|
|
|
// If its a naturalized dcmjs tag present on the instance, return.
|
|
if (instance[naturalizedTagOrWADOImageLoaderTag]) {
|
|
return instance[naturalizedTagOrWADOImageLoaderTag];
|
|
}
|
|
|
|
// Maybe its a legacy dicomImageLoader tag then:
|
|
return this._getCornerstoneDICOMImageLoaderTag(naturalizedTagOrWADOImageLoaderTag, instance);
|
|
}
|
|
|
|
/**
|
|
* Adds a new handler for the given tag. The handler will be provided an
|
|
* instance object that it can read values from.
|
|
*/
|
|
public addHandler(wadoImageLoaderTag: string, handler) {
|
|
WADO_IMAGE_LOADER[wadoImageLoaderTag] = handler;
|
|
}
|
|
|
|
_getCornerstoneDICOMImageLoaderTag(wadoImageLoaderTag, instance) {
|
|
let metadata = WADO_IMAGE_LOADER[wadoImageLoaderTag]?.(instance);
|
|
if (metadata) {
|
|
return metadata;
|
|
}
|
|
|
|
switch (wadoImageLoaderTag) {
|
|
case WADO_IMAGE_LOADER_TAGS.GENERAL_SERIES_MODULE:
|
|
const { SeriesDate, SeriesTime } = instance;
|
|
|
|
let seriesDate;
|
|
let seriesTime;
|
|
|
|
if (SeriesDate) {
|
|
seriesDate = dicomParser.parseDA(SeriesDate);
|
|
}
|
|
|
|
if (SeriesTime) {
|
|
seriesTime = dicomParser.parseTM(SeriesTime);
|
|
}
|
|
|
|
metadata = {
|
|
modality: instance.Modality,
|
|
seriesInstanceUID: instance.SeriesInstanceUID,
|
|
seriesNumber: toNumber(instance.SeriesNumber),
|
|
studyInstanceUID: instance.StudyInstanceUID,
|
|
seriesDate,
|
|
seriesTime,
|
|
};
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.PATIENT_STUDY_MODULE:
|
|
metadata = {
|
|
patientAge: toNumber(instance.PatientAge),
|
|
patientSize: toNumber(instance.PatientSize),
|
|
patientWeight: toNumber(instance.PatientWeight),
|
|
};
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.PATIENT_DEMOGRAPHIC_MODULE:
|
|
metadata = {
|
|
patientSex: instance.PatientSex,
|
|
};
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.IMAGE_PIXEL_MODULE:
|
|
metadata = {
|
|
samplesPerPixel: toNumber(instance.SamplesPerPixel),
|
|
photometricInterpretation: instance.PhotometricInterpretation,
|
|
rows: toNumber(instance.Rows),
|
|
columns: toNumber(instance.Columns),
|
|
bitsAllocated: toNumber(instance.BitsAllocated),
|
|
bitsStored: toNumber(instance.BitsStored),
|
|
highBit: toNumber(instance.HighBit),
|
|
pixelRepresentation: toNumber(instance.PixelRepresentation),
|
|
planarConfiguration: toNumber(instance.PlanarConfiguration),
|
|
pixelAspectRatio: toNumber(instance.PixelAspectRatio),
|
|
smallestPixelValue: toNumber(instance.SmallestPixelValue),
|
|
largestPixelValue: toNumber(instance.LargestPixelValue),
|
|
redPaletteColorLookupTableDescriptor: toNumber(
|
|
instance.RedPaletteColorLookupTableDescriptor
|
|
),
|
|
greenPaletteColorLookupTableDescriptor: toNumber(
|
|
instance.GreenPaletteColorLookupTableDescriptor
|
|
),
|
|
bluePaletteColorLookupTableDescriptor: toNumber(
|
|
instance.BluePaletteColorLookupTableDescriptor
|
|
),
|
|
redPaletteColorLookupTableData: fetchPaletteColorLookupTableData(
|
|
instance,
|
|
'RedPaletteColorLookupTableData',
|
|
'RedPaletteColorLookupTableDescriptor'
|
|
),
|
|
greenPaletteColorLookupTableData: fetchPaletteColorLookupTableData(
|
|
instance,
|
|
'GreenPaletteColorLookupTableData',
|
|
'GreenPaletteColorLookupTableDescriptor'
|
|
),
|
|
bluePaletteColorLookupTableData: fetchPaletteColorLookupTableData(
|
|
instance,
|
|
'BluePaletteColorLookupTableData',
|
|
'BluePaletteColorLookupTableDescriptor'
|
|
),
|
|
};
|
|
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.VOI_LUT_MODULE:
|
|
const { WindowCenter, WindowWidth, VOILUTFunction } = instance;
|
|
if (WindowCenter === undefined || WindowWidth === undefined) {
|
|
return;
|
|
}
|
|
const windowCenter = Array.isArray(WindowCenter) ? WindowCenter : [WindowCenter];
|
|
const windowWidth = Array.isArray(WindowWidth) ? WindowWidth : [WindowWidth];
|
|
|
|
metadata = {
|
|
windowCenter: toNumber(windowCenter),
|
|
windowWidth: toNumber(windowWidth),
|
|
voiLUTFunction: VOILUTFunction,
|
|
};
|
|
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.MODALITY_LUT_MODULE:
|
|
const { RescaleIntercept, RescaleSlope } = instance;
|
|
if (RescaleIntercept === undefined || RescaleSlope === undefined) {
|
|
return;
|
|
}
|
|
|
|
metadata = {
|
|
rescaleIntercept: toNumber(instance.RescaleIntercept),
|
|
rescaleSlope: toNumber(instance.RescaleSlope),
|
|
rescaleType: instance.RescaleType,
|
|
};
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.SOP_COMMON_MODULE:
|
|
metadata = {
|
|
sopClassUID: instance.SOPClassUID,
|
|
sopInstanceUID: instance.SOPInstanceUID,
|
|
};
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.PET_IMAGE_MODULE:
|
|
metadata = {
|
|
frameReferenceTime: instance.FrameReferenceTime,
|
|
actualFrameDuration: instance.ActualFrameDuration,
|
|
};
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.PET_ISOTOPE_MODULE:
|
|
const { RadiopharmaceuticalInformationSequence } = instance;
|
|
|
|
if (RadiopharmaceuticalInformationSequence) {
|
|
const RadiopharmaceuticalInformation = Array.isArray(
|
|
RadiopharmaceuticalInformationSequence
|
|
)
|
|
? RadiopharmaceuticalInformationSequence[0]
|
|
: RadiopharmaceuticalInformationSequence;
|
|
|
|
const { RadiopharmaceuticalStartTime, RadionuclideTotalDose, RadionuclideHalfLife } =
|
|
RadiopharmaceuticalInformation;
|
|
|
|
const radiopharmaceuticalInfo = {
|
|
radiopharmaceuticalStartTime: dicomParser.parseTM(RadiopharmaceuticalStartTime),
|
|
radionuclideTotalDose: RadionuclideTotalDose,
|
|
radionuclideHalfLife: RadionuclideHalfLife,
|
|
};
|
|
metadata = {
|
|
radiopharmaceuticalInfo,
|
|
};
|
|
}
|
|
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.OVERLAY_PLANE_MODULE:
|
|
const overlays = [];
|
|
|
|
for (let overlayGroup = 0x00; overlayGroup <= 0x1e; overlayGroup += 0x02) {
|
|
let groupStr = `60${overlayGroup.toString(16)}`;
|
|
|
|
if (groupStr.length === 3) {
|
|
groupStr = `600${overlayGroup.toString(16)}`;
|
|
}
|
|
|
|
const OverlayDataTag = `${groupStr}3000`;
|
|
const OverlayData = instance[OverlayDataTag];
|
|
|
|
if (!OverlayData) {
|
|
continue;
|
|
}
|
|
|
|
const OverlayRowsTag = `${groupStr}0010`;
|
|
const OverlayColumnsTag = `${groupStr}0011`;
|
|
const OverlayType = `${groupStr}0040`;
|
|
const OverlayOriginTag = `${groupStr}0050`;
|
|
const OverlayDescriptionTag = `${groupStr}0022`;
|
|
const OverlayLabelTag = `${groupStr}1500`;
|
|
const ROIAreaTag = `${groupStr}1301`;
|
|
const ROIMeanTag = `${groupStr}1302`;
|
|
const ROIStandardDeviationTag = `${groupStr}1303`;
|
|
const OverlayOrigin = instance[OverlayOriginTag];
|
|
|
|
let rows = 0;
|
|
if (instance[OverlayRowsTag] instanceof Array) {
|
|
// The DICOM VR for overlay rows is US (unsigned short).
|
|
const rowsInt16Array = new Uint16Array(instance[OverlayRowsTag][0]);
|
|
rows = rowsInt16Array[0];
|
|
} else {
|
|
rows = instance[OverlayRowsTag];
|
|
}
|
|
|
|
let columns = 0;
|
|
if (instance[OverlayColumnsTag] instanceof Array) {
|
|
// The DICOM VR for overlay columns is US (unsigned short).
|
|
const columnsInt16Array = new Uint16Array(instance[OverlayColumnsTag][0]);
|
|
columns = columnsInt16Array[0];
|
|
} else {
|
|
columns = instance[OverlayColumnsTag];
|
|
}
|
|
|
|
let x = 0;
|
|
let y = 0;
|
|
if (OverlayOrigin.length === 1) {
|
|
// The DICOM VR for overlay origin is SS (signed short) with a multiplicity of 2.
|
|
const originInt16Array = new Int16Array(OverlayOrigin[0]);
|
|
x = originInt16Array[0];
|
|
y = originInt16Array[1];
|
|
} else {
|
|
x = OverlayOrigin[0];
|
|
y = OverlayOrigin[1];
|
|
}
|
|
|
|
const overlay = {
|
|
rows: rows,
|
|
columns: columns,
|
|
type: instance[OverlayType],
|
|
x,
|
|
y,
|
|
pixelData: OverlayData,
|
|
description: instance[OverlayDescriptionTag],
|
|
label: instance[OverlayLabelTag],
|
|
roiArea: instance[ROIAreaTag],
|
|
roiMean: instance[ROIMeanTag],
|
|
roiStandardDeviation: instance[ROIStandardDeviationTag],
|
|
};
|
|
|
|
overlays.push(overlay);
|
|
}
|
|
|
|
metadata = {
|
|
overlays,
|
|
};
|
|
|
|
break;
|
|
|
|
case WADO_IMAGE_LOADER_TAGS.PATIENT_MODULE:
|
|
const { PatientName } = instance;
|
|
|
|
let patientName;
|
|
if (PatientName) {
|
|
patientName = PatientName.Alphabetic;
|
|
}
|
|
|
|
metadata = {
|
|
patientName,
|
|
patientId: instance.PatientID,
|
|
};
|
|
|
|
break;
|
|
|
|
case WADO_IMAGE_LOADER_TAGS.GENERAL_IMAGE_MODULE:
|
|
metadata = {
|
|
sopInstanceUID: instance.SOPInstanceUID,
|
|
instanceNumber: toNumber(instance.InstanceNumber),
|
|
lossyImageCompression: instance.LossyImageCompression,
|
|
lossyImageCompressionRatio: instance.LossyImageCompressionRatio,
|
|
lossyImageCompressionMethod: instance.LossyImageCompressionMethod,
|
|
};
|
|
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.GENERAL_STUDY_MODULE:
|
|
metadata = {
|
|
studyDescription: instance.StudyDescription,
|
|
studyDate: instance.StudyDate,
|
|
studyTime: instance.StudyTime,
|
|
accessionNumber: instance.AccessionNumber,
|
|
};
|
|
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.CINE_MODULE:
|
|
metadata = {
|
|
frameTime: instance.FrameTime,
|
|
numberOfFrames: instance.NumberOfFrames ? Number(instance.NumberOfFrames) : 1,
|
|
};
|
|
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.PER_SERIES_MODULE:
|
|
metadata = {
|
|
correctedImage: instance.CorrectedImage,
|
|
units: instance.Units,
|
|
decayCorrection: instance.DecayCorrection,
|
|
};
|
|
break;
|
|
case WADO_IMAGE_LOADER_TAGS.CALIBRATION_MODULE:
|
|
// map the DICOM tags to the cornerstone tags since cornerstone tags
|
|
// are camelCase and instance tags are all caps
|
|
metadata = {
|
|
sequenceOfUltrasoundRegions: instance.SequenceOfUltrasoundRegions?.map(region => {
|
|
return {
|
|
regionSpatialFormat: region.RegionSpatialFormat,
|
|
regionDataType: region.RegionDataType,
|
|
regionFlags: region.RegionFlags,
|
|
regionLocationMinX0: region.RegionLocationMinX0,
|
|
regionLocationMinY0: region.RegionLocationMinY0,
|
|
regionLocationMaxX1: region.RegionLocationMaxX1,
|
|
regionLocationMaxY1: region.RegionLocationMaxY1,
|
|
referencePixelX0: region.ReferencePixelX0,
|
|
referencePixelY0: region.ReferencePixelY0,
|
|
referencePixelPhysicalValueX: region.ReferencePixelPhysicalValueX,
|
|
referencePixelPhysicalValueY: region.ReferencePixelPhysicalValueY,
|
|
physicalUnitsXDirection: region.PhysicalUnitsXDirection,
|
|
physicalUnitsYDirection: region.PhysicalUnitsYDirection,
|
|
physicalDeltaX: region.PhysicalDeltaX,
|
|
physicalDeltaY: region.PhysicalDeltaY,
|
|
};
|
|
}),
|
|
};
|
|
break;
|
|
|
|
/**
|
|
* Below are the tags and not the modules since they are not really
|
|
* consistent with the modules above
|
|
*/
|
|
case 'temporalPositionIdentifier':
|
|
metadata = {
|
|
temporalPositionIdentifier: instance.TemporalPositionIdentifier,
|
|
};
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
return metadata;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the frameNumber information, depending on the url style
|
|
* wadors /frames/1
|
|
* wadouri &frame=1
|
|
* @param {*} imageId
|
|
* @returns
|
|
*/
|
|
getFrameInformationFromURL(imageId) {
|
|
function getInformationFromURL(informationString, separator) {
|
|
let result = '';
|
|
const splittedStr = imageId.split(informationString)[1];
|
|
if (splittedStr.includes(separator)) {
|
|
result = splittedStr.split(separator)[0];
|
|
} else {
|
|
result = splittedStr;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
if (imageId.includes('/frames')) {
|
|
return getInformationFromURL('/frames', '/');
|
|
}
|
|
if (imageId.includes('&frame=')) {
|
|
return getInformationFromURL('&frame=', '&');
|
|
}
|
|
return;
|
|
}
|
|
|
|
getUIDsFromImageID(imageId) {
|
|
if (!imageId) {
|
|
throw new Error('MetadataProvider::Empty imageId');
|
|
}
|
|
// TODO: adding csiv here is not really correct. Probably need to use
|
|
// metadataProvider.addImageIdToUIDs(imageId, {
|
|
// StudyInstanceUID,
|
|
// SeriesInstanceUID,
|
|
// SOPInstanceUID,
|
|
// })
|
|
// somewhere else
|
|
if (imageId.startsWith('wadors:')) {
|
|
const strippedImageId = imageId.split('/studies/')[1];
|
|
const splitImageId = strippedImageId.split('/');
|
|
|
|
return {
|
|
StudyInstanceUID: splitImageId[0], // Note: splitImageId[1] === 'series'
|
|
SeriesInstanceUID: splitImageId[2], // Note: splitImageId[3] === 'instances'
|
|
SOPInstanceUID: splitImageId[4],
|
|
frameNumber: splitImageId[6],
|
|
};
|
|
} else if (imageId.includes('?requestType=WADO')) {
|
|
const qs = queryString.parse(imageId);
|
|
|
|
return {
|
|
StudyInstanceUID: qs.studyUID,
|
|
SeriesInstanceUID: qs.seriesUID,
|
|
SOPInstanceUID: qs.objectUID,
|
|
frameNumber: qs.frameNumber,
|
|
};
|
|
}
|
|
|
|
// Maybe its a non-standard imageId
|
|
// check if the imageId starts with http:// or https:// using regex
|
|
// Todo: handle non http imageIds
|
|
let imageURI;
|
|
const urlRegex = /^(http|https|dicomfile):\/\//;
|
|
if (urlRegex.test(imageId)) {
|
|
imageURI = imageId;
|
|
} else {
|
|
imageURI = imageIdToURI(imageId);
|
|
}
|
|
|
|
// remove &frame=number from imageId
|
|
imageURI = imageURI.split('&frame=')[0];
|
|
|
|
const uids = this.imageURIToUIDs.get(imageURI);
|
|
const frameNumber = this.getFrameInformationFromURL(imageId) || '1';
|
|
|
|
if (uids && frameNumber !== undefined) {
|
|
return { ...uids, frameNumber };
|
|
}
|
|
return uids;
|
|
}
|
|
}
|
|
|
|
const metadataProvider = new MetadataProvider();
|
|
|
|
export default metadataProvider;
|
|
|
|
const WADO_IMAGE_LOADER = {
|
|
imagePlaneModule: instance => {
|
|
const { ImageOrientationPatient } = instance;
|
|
|
|
// Fallback for DX images.
|
|
// 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;
|
|
|
|
let rowCosines;
|
|
let columnCosines;
|
|
|
|
if (PixelSpacing) {
|
|
rowPixelSpacing = PixelSpacing[0];
|
|
columnPixelSpacing = PixelSpacing[1];
|
|
}
|
|
|
|
if (ImageOrientationPatient) {
|
|
rowCosines = ImageOrientationPatient.slice(0, 3);
|
|
columnCosines = ImageOrientationPatient.slice(3, 6);
|
|
}
|
|
|
|
return {
|
|
frameOfReferenceUID: instance.FrameOfReferenceUID,
|
|
rows: toNumber(instance.Rows),
|
|
columns: toNumber(instance.Columns),
|
|
imageOrientationPatient: toNumber(ImageOrientationPatient),
|
|
rowCosines: toNumber(rowCosines || [0, 1, 0]),
|
|
isDefaultValueSetForRowCosine: toNumber(rowCosines) ? false : true,
|
|
columnCosines: toNumber(columnCosines || [0, 0, -1]),
|
|
isDefaultValueSetForColumnCosine: toNumber(columnCosines) ? false : true,
|
|
imagePositionPatient: toNumber(instance.ImagePositionPatient || [0, 0, 0]),
|
|
sliceThickness: toNumber(instance.SliceThickness),
|
|
sliceLocation: toNumber(instance.SliceLocation),
|
|
pixelSpacing: toNumber(PixelSpacing || 1),
|
|
rowPixelSpacing: rowPixelSpacing ? toNumber(rowPixelSpacing) : null,
|
|
columnPixelSpacing: columnPixelSpacing ? toNumber(columnPixelSpacing) : null,
|
|
};
|
|
},
|
|
};
|
|
|
|
const WADO_IMAGE_LOADER_TAGS = {
|
|
// dicomImageLoader specific
|
|
GENERAL_SERIES_MODULE: 'generalSeriesModule',
|
|
PATIENT_STUDY_MODULE: 'patientStudyModule',
|
|
IMAGE_PIXEL_MODULE: 'imagePixelModule',
|
|
VOI_LUT_MODULE: 'voiLutModule',
|
|
MODALITY_LUT_MODULE: 'modalityLutModule',
|
|
SOP_COMMON_MODULE: 'sopCommonModule',
|
|
PET_IMAGE_MODULE: 'petImageModule',
|
|
PET_ISOTOPE_MODULE: 'petIsotopeModule',
|
|
PER_SERIES_MODULE: 'petSeriesModule',
|
|
OVERLAY_PLANE_MODULE: 'overlayPlaneModule',
|
|
PATIENT_DEMOGRAPHIC_MODULE: 'patientDemographicModule',
|
|
|
|
// react-cornerstone-viewport specific
|
|
PATIENT_MODULE: 'patientModule',
|
|
GENERAL_IMAGE_MODULE: 'generalImageModule',
|
|
GENERAL_STUDY_MODULE: 'generalStudyModule',
|
|
CINE_MODULE: 'cineModule',
|
|
CALIBRATION_MODULE: 'calibrationModule',
|
|
};
|
|
|
|
const INSTANCE = 'instance';
|