135 lines
4.5 KiB
Plaintext
135 lines
4.5 KiB
Plaintext
import { api } from 'dicomweb-client';
|
|
import dcmjs from 'dcmjs';
|
|
import { calculateSUVScalingFactors } from '@cornerstonejs/calculate-suv';
|
|
import { getPTImageIdInstanceMetadata } from './getPTImageIdInstanceMetadata';
|
|
import { utilities } from '@cornerstonejs/core';
|
|
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader';
|
|
|
|
import ptScalingMetaDataProvider from './ptScalingMetaDataProvider';
|
|
import getPixelSpacingInformation from './getPixelSpacingInformation';
|
|
import { convertMultiframeImageIds } from './convertMultiframeImageIds';
|
|
import removeInvalidTags from './removeInvalidTags';
|
|
|
|
const { DicomMetaDictionary } = dcmjs.data;
|
|
const { calibratedPixelSpacingMetadataProvider } = utilities;
|
|
|
|
/**
|
|
/**
|
|
* Uses dicomweb-client to fetch metadata of a study, cache it in cornerstone,
|
|
* and return a list of imageIds for the frames.
|
|
*
|
|
* Uses the app config to choose which study to fetch, and which
|
|
* dicom-web server to fetch it from.
|
|
*
|
|
* @returns {string[]} An array of imageIds for instances in the study.
|
|
*/
|
|
|
|
export default async function createImageIdsAndCacheMetaData({
|
|
StudyInstanceUID,
|
|
SeriesInstanceUID,
|
|
SOPInstanceUID = null,
|
|
wadoRsRoot,
|
|
client = null,
|
|
}) {
|
|
const SOP_INSTANCE_UID = '00080018';
|
|
const SERIES_INSTANCE_UID = '0020000E';
|
|
const MODALITY = '00080060';
|
|
|
|
const studySearchOptions = {
|
|
studyInstanceUID: StudyInstanceUID,
|
|
seriesInstanceUID: SeriesInstanceUID,
|
|
};
|
|
|
|
client = client || new api.DICOMwebClient({ url: wadoRsRoot });
|
|
const instances = await client.retrieveSeriesMetadata(studySearchOptions);
|
|
const modality = instances[0][MODALITY].Value[0];
|
|
let imageIds = instances.map((instanceMetaData) => {
|
|
const SeriesInstanceUID = instanceMetaData[SERIES_INSTANCE_UID].Value[0];
|
|
const SOPInstanceUIDToUse =
|
|
SOPInstanceUID || instanceMetaData[SOP_INSTANCE_UID].Value[0];
|
|
|
|
const prefix = 'wadors:';
|
|
|
|
const imageId =
|
|
prefix +
|
|
wadoRsRoot +
|
|
'/studies/' +
|
|
StudyInstanceUID +
|
|
'/series/' +
|
|
SeriesInstanceUID +
|
|
'/instances/' +
|
|
SOPInstanceUIDToUse +
|
|
'/frames/1';
|
|
|
|
cornerstoneDICOMImageLoader.wadors.metaDataManager.add(
|
|
imageId,
|
|
instanceMetaData
|
|
);
|
|
return imageId;
|
|
});
|
|
|
|
// if the image ids represent multiframe information, creates a new list with one image id per frame
|
|
// if not multiframe data available, just returns the same list given
|
|
imageIds = convertMultiframeImageIds(imageIds);
|
|
|
|
imageIds.forEach((imageId) => {
|
|
let instanceMetaData =
|
|
cornerstoneDICOMImageLoader.wadors.metaDataManager.get(imageId);
|
|
|
|
// It was using JSON.parse(JSON.stringify(...)) before but it is 8x slower
|
|
instanceMetaData = removeInvalidTags(instanceMetaData);
|
|
|
|
if (instanceMetaData) {
|
|
// Add calibrated pixel spacing
|
|
const metadata = DicomMetaDictionary.naturalizeDataset(instanceMetaData);
|
|
const pixelSpacing = getPixelSpacingInformation(metadata);
|
|
|
|
if (pixelSpacing) {
|
|
calibratedPixelSpacingMetadataProvider.add(imageId, {
|
|
rowPixelSpacing: parseFloat(pixelSpacing[0]),
|
|
columnPixelSpacing: parseFloat(pixelSpacing[1]),
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// we don't want to add non-pet
|
|
// Note: for 99% of scanners SUV calculation is consistent bw slices
|
|
if (modality === 'PT') {
|
|
const InstanceMetadataArray = [];
|
|
imageIds.forEach((imageId) => {
|
|
const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
|
|
|
|
// TODO: Temporary fix because static-wado is producing a string, not an array of values
|
|
// (or maybe dcmjs isn't parsing it correctly?)
|
|
// It's showing up like 'DECY\\ATTN\\SCAT\\DTIM\\RAN\\RADL\\DCAL\\SLSENS\\NORM'
|
|
// but calculate-suv expects ['DECY', 'ATTN', ...]
|
|
if (typeof instanceMetadata.CorrectedImage === 'string') {
|
|
instanceMetadata.CorrectedImage =
|
|
instanceMetadata.CorrectedImage.split('\\');
|
|
}
|
|
|
|
if (instanceMetadata) {
|
|
InstanceMetadataArray.push(instanceMetadata);
|
|
}
|
|
});
|
|
if (InstanceMetadataArray.length) {
|
|
try {
|
|
const suvScalingFactors = calculateSUVScalingFactors(
|
|
InstanceMetadataArray
|
|
);
|
|
InstanceMetadataArray.forEach((instanceMetadata, index) => {
|
|
ptScalingMetaDataProvider.addInstance(
|
|
imageIds[index],
|
|
suvScalingFactors[index]
|
|
);
|
|
});
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
}
|
|
|
|
return imageIds;
|
|
}
|