Skip to content

Commit

Permalink
feat(segmentGroups): use SEG metadata for segments label and color
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulHax committed Oct 3, 2024
1 parent 9a3982a commit 8db63b4
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 38 deletions.
20 changes: 18 additions & 2 deletions src/io/dicom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
readDicomTags,
readImageDicomFileSeries,
readOverlappingSegmentation,
ReadOverlappingSegmentationResult,
} from '@itk-wasm/dicom';

import itkConfig from '@/src/io/itk/itkConfig';
Expand Down Expand Up @@ -174,12 +175,27 @@ export async function readVolumeSlice(
return result.outputs[0].data as Image;
}

type Segment = {
SegmentLabel: string;
labelID: number;
recommendedDisplayRGBValue: [number, number, number];
};

type ReadOverlappingSegmentationMeta = {
segmentAttributes: Segment[][];
};

type ReadOverlappingSegmentationResultWithRealMeta =
ReadOverlappingSegmentationResult & {
metaInfo: ReadOverlappingSegmentationMeta;
};

export async function buildLabelMap(file: File) {
const inputImage = sanitizeFile(file);
const result = await readOverlappingSegmentation(inputImage, {
const result = (await readOverlappingSegmentation(inputImage, {
webWorker: getWorker(),
mergeSegments: true,
});
})) as ReadOverlappingSegmentationResultWithRealMeta;
return {
...result,
outputImage: result.segImage,
Expand Down
4 changes: 1 addition & 3 deletions src/store/datasets-dicom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export interface VolumeInfo {
const buildImage = async (seriesFiles: File[], modality: string) => {
if (modality === 'SEG') {
return {
modality,
modality: 'SEG',
builtImageResults: await DICOM.buildLabelMap(seriesFiles[0]),
messages:
seriesFiles.length > 1
Expand All @@ -61,7 +61,6 @@ const buildImage = async (seriesFiles: File[], modality: string) => {
};
}
return {
modality,
builtImageResults: await DICOM.buildImage(seriesFiles),
messages: [],
};
Expand All @@ -75,7 +74,6 @@ const constructImage = async (volumeKey: string, volumeInfo: VolumeInfo) => {
const image = vtkITKHelper.convertItkToVtkImage(
results.builtImageResults.outputImage
);
debugger;
return {
...results,
image,
Expand Down
58 changes: 25 additions & 33 deletions src/store/segmentGroups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,39 +203,31 @@ export const useSegmentGroupStore = defineStore('segmentGroup', () => {
delete metadataByID[id];
}

let lastColorIndex = 0;
function getNextColor() {
const color = DEFAULT_SEGMENT_MASKS[lastColorIndex].color;
lastColorIndex = (lastColorIndex + 1) % DEFAULT_SEGMENT_MASKS.length;
return [...color];
}

function decodeSegments(image: DataSelection) {
if (isRegularImage(image)) {
return structuredClone(DEFAULT_SEGMENT_MASKS);
// let lastColorIndex = 0;
// function getNextColor() {
// const color = DEFAULT_SEGMENT_MASKS[lastColorIndex].color;
// lastColorIndex = (lastColorIndex + 1) % DEFAULT_SEGMENT_MASKS.length;
// return [...color];
// }

async function decodeSegments(image: DataSelection) {
if (!isRegularImage(image)) {
// dicom image
const dicomStore = useDICOMStore();

const volumeBuildResults = await dicomStore.volumeBuildResults[image];
if (volumeBuildResults.modality === 'SEG') {
const segments =
volumeBuildResults.builtImageResults.metaInfo.segmentAttributes[0];
return segments.map((segment) => ({
value: segment.labelID,
name: segment.SegmentLabel,
color: [...segment.recommendedDisplayRGBValue, 255],
}));
}
}

const dicomStore = useDICOMStore();
const volumeInfo = dicomStore.volumeInfo[image];
const segmentSequence = undefined; // volumeInfo.SegmentSequence;
if (!segmentSequence) {
return [
{
value: 255,
name: volumeInfo.SeriesDescription || 'Unknown Segment',
color: getNextColor(),
},
];
}
// TODO convert Recommended Display CIELab Value (0062,000D) tag to a segment color
// TODO convert SegmentDescription (0062,0006) tag to a segment name
return [
{
value: 255,
name: volumeInfo.SeriesDescription || 'Unknown Segment',
color: [255, 0, 255, 255],
},
];
return structuredClone(DEFAULT_SEGMENT_MASKS);
}

/**
Expand Down Expand Up @@ -269,7 +261,7 @@ export const useSegmentGroupStore = defineStore('segmentGroup', () => {
}

const name = imageStore.metadata[imageID].name;
// Don't remove image if DICOM as user may have selected child image as primary selection by now
// Don't remove image if DICOM as user may have selected segment group image as primary selection by now
const deleteImage = isRegularImage(imageID);
if (deleteImage) {
imageStore.deleteData(imageID);
Expand All @@ -282,7 +274,7 @@ export const useSegmentGroupStore = defineStore('segmentGroup', () => {
: resampled;
const labelmapImage = toLabelMap(ownedMemoryImage);

const segments = decodeSegments(imageID);
const segments = await decodeSegments(imageID);
const { order, byKey } = normalizeForStore(segments, 'value');
const segmentGroupStore = useSegmentGroupStore();
segmentGroupStore.addLabelmap(labelmapImage, {
Expand Down

0 comments on commit 8db63b4

Please sign in to comment.