Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(examples): stack and volume segmentation #1684

Merged
merged 3 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 26 additions & 7 deletions packages/adapters/examples/segmentationStack/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ import { api } from "dicomweb-client";

import * as cornerstone from "@cornerstonejs/core";
import * as cornerstoneTools from "@cornerstonejs/tools";
import * as cornerstoneAdapters from "@cornerstonejs/adapters";

import { dicomMap } from "./demo";

import {
addButtonToToolbar,
addDropdownToToolbar,
addManipulationBindings,
addToggleButtonToToolbar,
addUploadToToolbar,
Expand All @@ -26,7 +24,7 @@ console.warn(
);

const { Enums: csEnums, RenderingEngine, utilities: csUtilities } = cornerstone;
const { ViewportType } = csEnums;
const { segmentation: csToolsSegmentation } = cornerstoneTools;
import {
readDicom,
loadDicom,
Expand All @@ -36,7 +34,8 @@ import {
restart,
getSegmentationIds,
handleFileSelect,
handleDragOver
handleDragOver,
createSegmentation
} from "../segmentationVolume/utils";

const referenceImageIds: string[] = [];
Expand Down Expand Up @@ -135,6 +134,13 @@ function loadDicom() {
renderingEngine.render();
}

function createSegmentationRepresentation() {
csToolsSegmentation.addLabelmapRepresentationToViewport(
state.viewportIds[0],
[{ segmentationId: state.segmentationId }]
);
}

// ============================= //
addButtonToToolbar({
id: "LOAD_DICOM",
Expand Down Expand Up @@ -169,16 +175,27 @@ addButtonToToolbar({
});

await loadSegmentation(arrayBuffer, state);
createSegmentationRepresentation();
},
container: group1
});

addUploadToToolbar({
id: "IMPORT_DICOM",
title: "Import DICOM",
onChange: (files: FileList) => {
readDicom(files, state);
loadDicom();
onChange: async (files: FileList) => {
await readDicom(files, state);
await loadDicom();
},
container: group2
});

addButtonToToolbar({
id: "CREATE_SEGMENTATION",
title: "Create Empty SEG",
onClick: async () => {
await createSegmentation(state);
createSegmentationRepresentation();
},
container: group2
});
Expand All @@ -190,6 +207,8 @@ addUploadToToolbar({
for (const file of files) {
await readSegmentation(file, state);
}

createSegmentationRepresentation();
},
container: group2
});
Expand Down
31 changes: 29 additions & 2 deletions packages/adapters/examples/segmentationVolume/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@ console.warn(
);

const { utilities: csUtilities } = cornerstone;
const { segmentation: csToolsSegmentation } = cornerstoneTools;
import {
readDicom,
readSegmentation,
loadSegmentation,
exportSegmentation,
handleFileSelect,
handleDragOver,
restart
restart,
createSegmentation
} from "../segmentationVolume/utils";

setTitleAndDescription(
Expand Down Expand Up @@ -158,6 +160,15 @@ async function loadDicom() {
renderingEngine.render();
}

function createSegmentationRepresentation() {
const segMap = {
[state.viewportIds[0]]: [{ segmentationId: state.segmentationId }],
[state.viewportIds[1]]: [{ segmentationId: state.segmentationId }],
[state.viewportIds[2]]: [{ segmentationId: state.segmentationId }]
};

csToolsSegmentation.addLabelmapRepresentationToViewportMap(segMap);
}
// ============================= //
addButtonToToolbar({
id: "LOAD_DICOM",
Expand Down Expand Up @@ -191,14 +202,28 @@ addButtonToToolbar({
});

await loadSegmentation(arrayBuffer, state);
createSegmentationRepresentation();
},
container: group1
});

addUploadToToolbar({
id: "IMPORT_DICOM",
title: "Import DICOM",
onChange: (files: FileList) => readDicom(files, state),
onChange: async (files: FileList) => {
await readDicom(files, state);
await loadDicom();
},
container: group2
});

addButtonToToolbar({
id: "CREATE_SEGMENTATION",
title: "Create Empty SEG",
onClick: async () => {
await createSegmentation(state);
createSegmentationRepresentation();
},
container: group2
});

Expand All @@ -213,6 +238,8 @@ addUploadToToolbar({
for (const file of files) {
await readSegmentation(file, state);
}

createSegmentationRepresentation();
},
container: group2
});
Expand Down
78 changes: 35 additions & 43 deletions packages/adapters/examples/segmentationVolume/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,46 @@ import * as cornerstoneDicomImageLoader from "@cornerstonejs/dicom-image-loader"
import * as cornerstoneAdapters from "@cornerstonejs/adapters";
import dcmjs from "dcmjs";

const {
cache,
imageLoader,
metaData,
utilities: csUtilities,
volumeLoader
} = cornerstone;
const { cache, imageLoader, metaData } = cornerstone;
const { segmentation: csToolsSegmentation } = cornerstoneTools;
const { wadouri } = cornerstoneDicomImageLoader;
const { downloadDICOMData } = cornerstoneAdapters.helpers;
const { Cornerstone3D } = cornerstoneAdapters.adaptersSEG;

export async function readDicom(files: FileList, state) {
if (files.length <= 1) {
console.error(
"Viewport volume does not support just one image, it must be two or more images"
);
return;
}

for (const file of files) {
const imageId = wadouri.fileManager.add(file);
await imageLoader.loadAndCacheImage(imageId);
state.referenceImageIds.push(imageId);
}
}

export async function createSegmentation(state) {
const { referenceImageIds, segmentationId } = state;

const derivedSegmentationImages =
await imageLoader.createAndCacheDerivedLabelmapImages(
referenceImageIds
);

const derivedSegmentationImageIds = derivedSegmentationImages.map(
image => image.imageId
);

csToolsSegmentation.addSegmentations([
{
segmentationId,
representation: {
type: cornerstoneTools.Enums.SegmentationRepresentations
.Labelmap,
data: {
imageIds: derivedSegmentationImageIds
}
}
}
]);
}

export async function readSegmentation(file: File, state) {
const imageId = wadouri.fileManager.add(file);
const image = await imageLoader.loadAndCacheImage(imageId);
Expand All @@ -52,8 +65,7 @@ export async function readSegmentation(file: File, state) {
}

export async function loadSegmentation(arrayBuffer: ArrayBuffer, state) {
const { referenceImageIds, skipOverlapping, viewportIds, segmentationId } =
state;
const { referenceImageIds, skipOverlapping, segmentationId } = state;

const generateToolState =
await Cornerstone3D.Segmentation.generateToolState(
Expand All @@ -72,35 +84,15 @@ export async function loadSegmentation(arrayBuffer: ArrayBuffer, state) {
return;
}

const derivedSegmentationImages =
await imageLoader.createAndCacheDerivedLabelmapImages(
referenceImageIds
);

const derivedSegmentationImageIds = derivedSegmentationImages.map(
image => image.imageId
);
await createSegmentation(state);

csToolsSegmentation.addSegmentations([
{
segmentationId,
representation: {
type: cornerstoneTools.Enums.SegmentationRepresentations
.Labelmap,
data: {
imageIds: derivedSegmentationImageIds
}
}
}
]);

const segMap = {
[viewportIds[0]]: [{ segmentationId }],
[viewportIds[1]]: [{ segmentationId }],
[viewportIds[2]]: [{ segmentationId }]
};
const segmentation =
csToolsSegmentation.state.getSegmentation(segmentationId);

await csToolsSegmentation.addLabelmapRepresentationToViewportMap(segMap);
const { imageIds } = segmentation.representationData.Labelmap;
const derivedSegmentationImages = imageIds.map(imageId =>
cache.getImage(imageId)
);

const volumeScalarData = new Uint8Array(
generateToolState.labelmapBufferArray[0]
Expand Down
2 changes: 1 addition & 1 deletion utils/ExampleRunner/template-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const rspack = require('@rspack/core');

module.exports = {
mode: 'development',
devtool: 'source-map',
devtool: 'eval-source-map',
plugins: [
new rspack.HtmlRspackPlugin({
template: '${root.replace(/\\/g, '/')}/utils/ExampleRunner/template.html',
Expand Down
Loading