2020-06-03 19:12:13 +02:00
|
|
|
import id from './id';
|
|
|
|
|
import { utils } from '@ohif/core';
|
|
|
|
|
|
|
|
|
|
const sopClassHandlerName = 'dicom-sr';
|
|
|
|
|
|
|
|
|
|
const sopClassUids = [
|
|
|
|
|
'1.2.840.10008.5.1.4.1.1.88.11', //BASIC_TEXT_SR:
|
|
|
|
|
'1.2.840.10008.5.1.4.1.1.88.22', //ENHANCED_SR:
|
|
|
|
|
'1.2.840.10008.5.1.4.1.1.88.33', //COMPREHENSIVE_SR:
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const scoordTypes = ['POINT', 'MULTIPOINT', 'POLYLINE', 'CIRCLE', 'ELLIPSE'];
|
|
|
|
|
|
|
|
|
|
const CodeNameCodeSequenceValues = {
|
|
|
|
|
ImagingMeasurementReport: '126000',
|
|
|
|
|
ImageLibrary: '111028',
|
|
|
|
|
ImagingMeasurements: '126010',
|
|
|
|
|
MeasurementGroup: '125007',
|
|
|
|
|
ImageLibraryGroup: '126200',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Basic SOPClassHandler:
|
|
|
|
|
* - For all Image types that are stackable, create
|
|
|
|
|
* a displaySet with a stack of images
|
|
|
|
|
*
|
|
|
|
|
* @param {Array} sopClassHandlerModules List of SOP Class Modules
|
|
|
|
|
* @param {SeriesMetadata} series The series metadata object from which the display sets will be created
|
|
|
|
|
* @returns {Array} The list of display sets created for the given series object
|
|
|
|
|
*/
|
|
|
|
|
function getDisplaySetsFromSeries(instances) {
|
|
|
|
|
// If the series has no instances, stop here
|
|
|
|
|
if (!instances || !instances.length) {
|
|
|
|
|
throw new Error('No instances were provided');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const instance = instances[0];
|
|
|
|
|
|
|
|
|
|
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance;
|
|
|
|
|
|
|
|
|
|
const { ConceptNameCodeSequence, ContentSequence } = instance;
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
ConceptNameCodeSequence.CodeValue !==
|
|
|
|
|
CodeNameCodeSequenceValues.ImagingMeasurementReport
|
|
|
|
|
) {
|
|
|
|
|
console.warn(
|
|
|
|
|
'Only support Imaging Measurement Report SRs (TID1500) for now'
|
|
|
|
|
);
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const referencedImages = _getReferencedImagesList(ContentSequence);
|
|
|
|
|
|
|
|
|
|
const measurements = _getMeasurements(ContentSequence, SOPInstanceUID);
|
|
|
|
|
|
|
|
|
|
const displaySet = {
|
|
|
|
|
plugin: id,
|
|
|
|
|
Modality: 'SR',
|
|
|
|
|
displaySetInstanceUID: utils.guid(),
|
|
|
|
|
SOPInstanceUID,
|
|
|
|
|
SeriesInstanceUID,
|
|
|
|
|
StudyInstanceUID,
|
|
|
|
|
SOPClassHandlerId: `${id}.sopClassHandlerModule.${sopClassHandlerName}`,
|
|
|
|
|
referencedImages,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return [displaySet];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getSopClassHandlerModule() {
|
|
|
|
|
return [
|
|
|
|
|
{
|
|
|
|
|
name: sopClassHandlerName,
|
|
|
|
|
sopClassUids,
|
|
|
|
|
getDisplaySetsFromSeries,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _getMeasurements(
|
|
|
|
|
ImagingMeasurementReportContentSequence,
|
|
|
|
|
SOPInstanceUID
|
|
|
|
|
) {
|
|
|
|
|
const ImagingMeasurements = ImagingMeasurementReportContentSequence.find(
|
|
|
|
|
item =>
|
|
|
|
|
item.ConceptNameCodeSequence.CodeValue ===
|
|
|
|
|
CodeNameCodeSequenceValues.ImagingMeasurements
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (SOPInstanceUID === '2.25.435452399240481307327287169369305113868') {
|
|
|
|
|
debugger;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-04 11:34:43 +02:00
|
|
|
const MeasurementGroups = _getSequenceAsArray(
|
2020-06-03 19:12:13 +02:00
|
|
|
ImagingMeasurements.ContentSequence
|
2020-06-04 11:34:43 +02:00
|
|
|
).filter(
|
2020-06-03 19:12:13 +02:00
|
|
|
item =>
|
|
|
|
|
item.ConceptNameCodeSequence.CodeValue ===
|
|
|
|
|
CodeNameCodeSequenceValues.MeasurementGroup
|
|
|
|
|
);
|
|
|
|
|
|
2020-06-04 11:34:43 +02:00
|
|
|
const measurements = [];
|
2020-06-03 19:12:13 +02:00
|
|
|
|
2020-06-04 11:34:43 +02:00
|
|
|
MeasurementGroups.forEach(MeasurementGroup => {
|
|
|
|
|
const measurement = _processMeasurementGroup(MeasurementGroup);
|
|
|
|
|
|
|
|
|
|
if (measurement) {
|
|
|
|
|
measurements.push(measurement);
|
|
|
|
|
}
|
|
|
|
|
});
|
2020-06-03 19:12:13 +02:00
|
|
|
|
|
|
|
|
_getSequenceAsArray(MeasurementGroup.ContentSequence).forEach(item => {});
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-04 11:34:43 +02:00
|
|
|
function _processMeasurementGroup(MeasurementGroup) {
|
|
|
|
|
const contentItemNum = _getSequenceAsArray(
|
|
|
|
|
MeasurementGroup.ContentSequence
|
|
|
|
|
).find(group => group.ValueType === 'NUM');
|
|
|
|
|
|
|
|
|
|
// TODO: Need to process MeasurementGroups as they may be implictly linked, or explictly linked by tracking uids.
|
|
|
|
|
|
|
|
|
|
// TODO -> Look at RelationshipType => Contains means
|
|
|
|
|
|
|
|
|
|
debugger;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-03 19:12:13 +02:00
|
|
|
function _getReferencedImagesList(ImagingMeasurementReportContentSequence) {
|
|
|
|
|
const ImageLibrary = ImagingMeasurementReportContentSequence.find(
|
|
|
|
|
item =>
|
|
|
|
|
item.ConceptNameCodeSequence.CodeValue ===
|
|
|
|
|
CodeNameCodeSequenceValues.ImageLibrary
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const ImageLibraryGroup = _getSequenceAsArray(
|
|
|
|
|
ImageLibrary.ContentSequence
|
|
|
|
|
).find(
|
|
|
|
|
item =>
|
|
|
|
|
item.ConceptNameCodeSequence.CodeValue ===
|
|
|
|
|
CodeNameCodeSequenceValues.ImageLibraryGroup
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const referencedImages = [];
|
|
|
|
|
|
|
|
|
|
_getSequenceAsArray(ImageLibraryGroup.ContentSequence).forEach(item => {
|
|
|
|
|
const { ReferencedSOPSequence } = item;
|
|
|
|
|
const {
|
|
|
|
|
ReferencedSOPClassUID,
|
|
|
|
|
ReferencedSOPInstanceUID,
|
|
|
|
|
} = ReferencedSOPSequence;
|
|
|
|
|
|
|
|
|
|
referencedImages.push({ ReferencedSOPClassUID, ReferencedSOPInstanceUID });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return referencedImages;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _getSequenceAsArray(sequence) {
|
|
|
|
|
return Array.isArray(sequence) ? sequence : [sequence];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default getSopClassHandlerModule;
|