diff --git a/src/io/dicom.ts b/src/io/dicom.ts index fed1a7b5..f0d27e63 100644 --- a/src/io/dicom.ts +++ b/src/io/dicom.ts @@ -1,10 +1,21 @@ import { runPipeline, TextStream, InterfaceTypes, Image } from 'itk-wasm'; -import { readDicomTags, readImageDicomFileSeries } from '@itk-wasm/dicom'; +import { + readDicomTags, + readImageDicomFileSeries, + readOverlappingSegmentation, + setPipelinesBaseUrl, + setPipelineWorkerUrl, +} from '@itk-wasm/dicom'; import itkConfig from '@/src/io/itk/itkConfig'; import { getDicomSeriesWorkerPool, getWorker } from '@/src/io/itk/worker'; +// Must be set at runtime as new version of @itk-wasm/dicom does not pickup +// build time `../itkConfig` alias remap. +setPipelinesBaseUrl(itkConfig.pipelinesUrl); +setPipelineWorkerUrl(itkConfig.pipelineWorkerUrl); + export interface TagSpec { name: string; tag: string; @@ -176,13 +187,19 @@ export async function readVolumeSlice( * @param {File[]} seriesFiles the set of files to build volume from * @returns ItkImage */ -export async function buildImage(seriesFiles: File[]) { +export async function buildImage(seriesFiles: File[], modality: string) { const inputImages = seriesFiles.map((file) => sanitizeFile(file)); + if (modality === 'SEG') { + const result = await readOverlappingSegmentation(inputImages[0], { + webWorker: getWorker(), + }); + console.log(result.metaInfo); + return result.segImage; + } const result = await readImageDicomFileSeries({ webWorkerPool: getDicomSeriesWorkerPool(), inputImages, singleSortedSeries: false, }); - return result.outputImage; } diff --git a/src/store/datasets-dicom.ts b/src/store/datasets-dicom.ts index 41da3478..341708d4 100644 --- a/src/store/datasets-dicom.ts +++ b/src/store/datasets-dicom.ts @@ -143,12 +143,12 @@ export const getWindowLevels = (info: VolumeInfo) => { return widths.map((width, i) => ({ width, level: levels[i] })); }; -const constructImage = async (volumeKey: string) => { +const constructImage = async (volumeKey: string, volumeInfo: VolumeInfo) => { const fileStore = useFileStore(); const files = fileStore.getFiles(volumeKey); if (!files) throw new Error('No files for volume key'); const image = vtkITKHelper.convertItkToVtkImage( - await DICOM.buildImage(files) + await DICOM.buildImage(files, volumeInfo.Modality) ); return image; }; @@ -196,7 +196,11 @@ export const useDICOMStore = defineStore('dicom', { Object.entries(volumeToFiles).map(async ([volumeKey, files]) => { // Read tags of first file if (!(volumeKey in this.volumeInfo)) { - const tags = await readDicomTags(files[0]); + const rawTags = await readDicomTags(files[0]); + // trim whitespace from all values + const tags = Object.fromEntries( + Object.entries(rawTags).map(([key, value]) => [key, value.trim()]) + ); // TODO parse the raw string values const patient = { PatientID: tags.PatientID || ANONYMOUS_PATIENT_ID, @@ -398,7 +402,7 @@ export const useDICOMStore = defineStore('dicom', { : []; // actually build volume or wait for existing build? const newImagePromise = buildNeeded - ? constructImage(volumeKey) + ? constructImage(volumeKey, this.volumeInfo[volumeKey]) : this.volumeImageData[volumeKey]; // let other calls to buildVolume reuse this constructImage work this.volumeImageData[volumeKey] = newImagePromise;