Skip to content

[Bug] I'm using the Pet+CT fusion feature, but the loaded Pet image has some issues. #2524

@woaihengniu

Description

@woaihengniu

Describe the Bug

I'm using the PT+CT fusion feature, but the loaded PT image has some issues—the PET image lacks window width and window level information.
I'm using the wadoui protocol—is this protocol not supported for loading PET+CT fusion images?

Image

use Rectangle ROI Tool: The measured data isn't correct either.

Image

Steps to Reproduce

1.init();
2 .Before loading the images, I always use ImageLoader to cache them first, and only load the images after they've been fully cached.

imageLoader
.loadAndCacheImage(url)
.then(async (image) => {
let instanceMetaData = metaData.get('instance', url);
console.log(instanceMetaData, 'instanceMetaData');
if (instanceMetaData) {
const pixelSpacingInformation = getPixelSpacingInformation(instanceMetaData);
const pixelSpacing = pixelSpacingInformation?.PixelSpacing;
if (pixelSpacing) {
calibratedPixelSpacingMetadataProvider.add(url, {
rowPixelSpacing: parseFloat(pixelSpacing[0]),
columnPixelSpacing: parseFloat(pixelSpacing[1]),
type: pixelSpacingInformation.type,
});
}
}
const Modality = image.data.string('x00080060');
if (Modality.toLowerCase() === 'pt') {
const instanceMetaData = getPTImageIdInstanceMetadata(url);
if (typeof instanceMetaData.CorrectedImage === 'string') {
instanceMetaData.CorrectedImage = instanceMetaData.CorrectedImage.split('\');
}
const suvScalingFactor = calculateSUVScalingFactors([instanceMetaData]);
console.log(suvScalingFactor, 'suvScalingFactor');
ptScalingMetaDataProvider.addInstance(url, suvScalingFactor);
}
loadingSet.delete(url);
resolve(image);
}) .catch((error) => {
loadingSet.delete(url);
reject(error);
}) .finally(() => {
running.value--;
waiting.value = queue.length;
dequeue();
});

3.load image

const loadImages = async () => {
if (!isMergeFirst.value) {
ptImageIds = currentDragItem.value.image;
ptVolumeId.value = utilities.uuidv4();
ptVolume = await volumeLoader.createAndCacheVolume(ptVolumeId.value, {
imageIds: ptImageIds,
});
await ptVolume.load();

    if (ptViewports.value.length > 0) {
        let viewportIds = ptViewports.value.map(viewport => viewport.viewportId);
        await setVolumesForViewports(
            renderingEngine,
            [
                {
                    volumeId: ptVolumeId.value,
                    callback: setPetTransferFunctionForVolumeActor,
                },
            ],
            viewportIds
        );
    }
    if (fusionViewports.value.length > 0) {
         const viewportIdsFusion = fusionViewports.value.map(viewport => viewport.viewportId);
         await setVolumesForViewports(
             renderingEngine,
             [
                 {
                     volumeId: ctVolumeId.value,
                       callback: setCtTransferFunctionForVolumeActor,
                 },
                 {
                     volumeId: ptVolumeId.value,
                     callback: setPetColorMapTransferFunctionForVolumeActor,
                 },
             ],
             viewportIdsFusion
         );
    }

    if (mipViewports.value.length > 0) {
        const ptVolumeDimensions = ptVolume.dimensions;
        const slabThickness = Math.sqrt(
            ptVolumeDimensions[0] * ptVolumeDimensions[0] +
            ptVolumeDimensions[1] * ptVolumeDimensions[1] +
            ptVolumeDimensions[2] * ptVolumeDimensions[2]
        );
        let viewportIdsMip = mipViewports.value.map(viewport => viewport.viewportId);
        await setVolumesForViewports(
            renderingEngine,
            [
                {
                    volumeId: ptVolumeId.value,
                    callback: setPetTransferFunctionForVolumeActor,
                    blendMode: Enums.BlendModes.MAXIMUM_INTENSITY_BLEND,
                    slabThickness,
                },
            ],
            viewportIdsMip
        );
    }
    if (!isFirstPet.value) {    
        initializeCameraSync();
        setUpToolGroups();
        setUpSynchronizers();
    }
    isFirstPet.value = true;
    mergeDicomConfigs.value[useConfigsIndex.value].viewports.forEach((viewport, index) => {
        viewport?.viewportInfo?.forEach((info) => {
            mergeDicomStore.getViewportWwWlByViewportId(info.viewportId)();
        })
    });
}
if (isMergeFirst.value) {
    isMergeFirst.value = false;
    const isLoaded = await checkAllImagesLoaded(ctImageIds);
    ctVolume = await volumeLoader.createAndCacheVolume(ctVolumeId.value, {
        imageIds: ctImageIds,
    });
    await ctVolume.load();
    if (ctViewports.value.length > 0) {
        let viewportIds = ctViewports.value.map(viewport => viewport.viewportId);
        await setVolumesForViewports(
            renderingEngine,
            [
                {
                    volumeId: ctVolumeId.value,
                    callback: setCtTransferFunctionForVolumeActor,
                },
            ],
            viewportIds
        );
    }
}
renderingEngine.render();

}

The current behavior

The loaded PET image is incorrect—it appears as a black block.
After I calculate the window width and window level based on the PET image and apply those values to the viewport, the image displays correctly. However, it doesn't show SUV values like in the example. Moreover, when I add the ViewportColorbar component, it displays values such as 10000, 20000, 30000—these appear to be raw pixel values rather than SUV values.

The expected behavior

Load the PET image correctly.
Load the fused image correctly.

System Information

win10
cornerstonejs/core 4.13.1
edge 143.0.3650.80

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions