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

Cannot destructure property 'pixelRepresentation' #180

Closed
zixiCat opened this issue Aug 18, 2022 · 11 comments
Closed

Cannot destructure property 'pixelRepresentation' #180

zixiCat opened this issue Aug 18, 2022 · 11 comments

Comments

@zixiCat
Copy link

zixiCat commented Aug 18, 2022

When I use wadouri in volume type and then invoke volumeLoader.createAndCacheVolume , it will throw this error. Stack type is okay
image
image

@zhoualibaba
Copy link

@zixiCat
I think you may not add the metadata into the cornerstoneWADOImageLoader.

@IbrahimCSAE
Copy link
Collaborator

IbrahimCSAE commented Aug 25, 2022

you need to add the metadata to cornerstoneWADOImageLoader first before creating a volume

you can use a function similar to this

    cacheMetaData: async function (series) {
      let wadoRsRoot = `${window.location.origin}/dicom-web`;
      const client = new dicomwebClient.api.DICOMwebClient({ url: wadoRsRoot });
      const studyInstanceUID = series["0020000D"]["Value"][0];
      const seriesInstanceUID = series["0020000E"]["Value"][0];
      let instances = await client.retrieveSeriesMetadata({
        studyInstanceUID: studyInstanceUID,
        seriesInstanceUID: seriesInstanceUID,
      });
      const imageIds = instances.map((instanceMetaData) => {
        const SeriesInstanceUID = instanceMetaData["0020000E"].Value[0];
        const SOPInstanceUID = instanceMetaData["00080018"].Value[0];
        const prefix = "wadors:";
        const imageId = `${prefix}${wadoRsRoot}/studies/${studyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}/frames/1`;
        cornerstoneWADOImageLoader.wadors.metaDataManager.add(imageId, instanceMetaData);
        return imageId;
      });
      return imageIds;
    },

You can then pass the returned imageIds to createAndCacheVolume.

@zixiCat
Copy link
Author

zixiCat commented Aug 27, 2022

@IbrahimCSAE
I mean I want to display local dicom files by using wadouri prefix, not wadors , is there any way to get these UID?(studyInstanceUID, seriesInstanceUID)

@IbrahimCSAE
Copy link
Collaborator

I don't know the exact process, but I think that they need to be loaded into memory and parsed first, I don't think you can just pass the disk location of the file to the function

@zixiCat
Copy link
Author

zixiCat commented Oct 11, 2022 via email

@JwRicauter
Copy link

Hey, I have the same problem but in production, in my local i don't have this problem.

here I call my custom method createImageIdsAndCacheMetaData

  await initProviders();
  await initCornerstoneWADOImageLoader()
  await initVolumeLoader()
  await cornerstone3D.init();
  await cornerstone3DTools.init();




  const imageIds = await createImageIdsAndCacheMetaData({
    StudyInstanceUID: caseId,
    SeriesInstanceUID: imageId,
    wadoRsRoot: process.env.REACT_APP_WADO_RS_ROOT,
    type: 'VOLUME',
  });


  // Define a volume in memory
  const volume = await volumeLoader.createAndCacheVolume(volumeId, {
    imageIds,
  });

and in that method I insert the metadata:

const client = new api.DICOMwebClient({ url: wadoRsRoot });
  const instances = await client.retrieveSeriesMetadata(studySearchOptions);
  const modality = instances[0][MODALITY].Value[0];

  const imageIds = instances.map((instanceMetaData) => {
    const SeriesInstanceUID = instanceMetaData[SERIES_INSTANCE_UID].Value[0];
    const SOPInstanceUID = instanceMetaData[SOP_INSTANCE_UID].Value[0];
    const prefix = type === VOLUME ? 'streaming-wadors:' : 'wadors:';

    const imageId =
      prefix +
      wadoRsRoot +
      '/studies/' +
      StudyInstanceUID +
      '/series/' +
      SeriesInstanceUID +
      '/instances/' +
      SOPInstanceUID +
      '/frames/1';

    cornerstoneWADOImageLoader.wadors.metaDataManager.add(
      imageId,
      instanceMetaData
    );

    WADORSHeaderProvider.addInstance(imageId, instanceMetaData);

    // Add calibrated pixel spacing
    const m = JSON.parse(JSON.stringify(instanceMetaData));
    const instance = DicomMetaDictionary.naturalizeDataset(m);
    const pixelSpacing = getPixelSpacingInformation(instance);

    calibratedPixelSpacingMetadataProvider.add(
      imageId,
      pixelSpacing.map((s) => parseFloat(s))
    );

    return imageId;
  });
  

idk if it's a cache thing because in my local server works but in production this messages jumps out 😢

@IbrahimCSAE
Copy link
Collaborator

Hey, I have the same problem but in production, in my local i don't have this problem.

here I call my custom method createImageIdsAndCacheMetaData

  await initProviders();
  await initCornerstoneWADOImageLoader()
  await initVolumeLoader()
  await cornerstone3D.init();
  await cornerstone3DTools.init();




  const imageIds = await createImageIdsAndCacheMetaData({
    StudyInstanceUID: caseId,
    SeriesInstanceUID: imageId,
    wadoRsRoot: process.env.REACT_APP_WADO_RS_ROOT,
    type: 'VOLUME',
  });


  // Define a volume in memory
  const volume = await volumeLoader.createAndCacheVolume(volumeId, {
    imageIds,
  });

and in that method I insert the metadata:

const client = new api.DICOMwebClient({ url: wadoRsRoot });
  const instances = await client.retrieveSeriesMetadata(studySearchOptions);
  const modality = instances[0][MODALITY].Value[0];

  const imageIds = instances.map((instanceMetaData) => {
    const SeriesInstanceUID = instanceMetaData[SERIES_INSTANCE_UID].Value[0];
    const SOPInstanceUID = instanceMetaData[SOP_INSTANCE_UID].Value[0];
    const prefix = type === VOLUME ? 'streaming-wadors:' : 'wadors:';

    const imageId =
      prefix +
      wadoRsRoot +
      '/studies/' +
      StudyInstanceUID +
      '/series/' +
      SeriesInstanceUID +
      '/instances/' +
      SOPInstanceUID +
      '/frames/1';

    cornerstoneWADOImageLoader.wadors.metaDataManager.add(
      imageId,
      instanceMetaData
    );

    WADORSHeaderProvider.addInstance(imageId, instanceMetaData);

    // Add calibrated pixel spacing
    const m = JSON.parse(JSON.stringify(instanceMetaData));
    const instance = DicomMetaDictionary.naturalizeDataset(m);
    const pixelSpacing = getPixelSpacingInformation(instance);

    calibratedPixelSpacingMetadataProvider.add(
      imageId,
      pixelSpacing.map((s) => parseFloat(s))
    );

    return imageId;
  });
  

idk if it's a cache thing because in my local server works but in production this messages jumps out 😢

Do u have a demo link where the error pops up?

@JwRicauter
Copy link

Yes there is a link but is not public yet, I have to give you the credentials.

However, I'm printing the naturalizedDataset variable in WADORSHeaderProvider and print all the metadata variables correctly:

-- Production (with the error)
Captura de Pantalla 2022-10-21 a la(s) 12 24 31

-- Same thing in development ( no error )
Captura de Pantalla 2022-10-21 a la(s) 12 25 28

@JwRicauter
Copy link

Yep, it match 😢

this is the first imageId resulting of createImageIdsAndCacheMetaData function

Captura de Pantalla 2022-10-27 a la(s) 9 57 16

and this is the imageIds object of makeVolumeMetadata

Captura de Pantalla 2022-10-27 a la(s) 10 00 03

I will attach the run function, but it's the same of one of the examples.

/*                   -- VOLUME --                  */

const viewportId1 = 'CT_AXIAL';
const viewportId2 = 'CT_SAGITTAL';
const viewportId3 = 'CT_CORONAL';

const viewportColors = {
  [viewportId1]: 'rgb(200, 0, 0)', [viewportId2]: 'rgb(200, 200, 0)', [viewportId3]: 'rgb(0, 200, 0)',
};

const viewportReferenceLineControllable = [
  viewportId1, viewportId2, viewportId3,
];

const viewportReferenceLineDraggableRotatable = [
  viewportId1, viewportId2, viewportId3,
];

const viewportReferenceLineSlabThicknessControlsOn = [
  viewportId1, viewportId2, viewportId3,
];

const getReferenceLineColor = (viewportId) => {
  return viewportColors[viewportId];
}

const getReferenceLineControllable = (viewportId) => {
  const index = viewportReferenceLineControllable.indexOf(viewportId);
  return index !== -1;
}

const getReferenceLineDraggableRotatable = (viewportId) => {
  const index = viewportReferenceLineDraggableRotatable.indexOf(viewportId);
  return index !== -1;
}

const getReferenceLineSlabThicknessControlsOn = (viewportId) => {
  const index =
    viewportReferenceLineSlabThicknessControlsOn.indexOf(viewportId);
  return index !== -1;
}


const volumeLoaderScheme = 'cornerstoneStreamingImageVolume'; // Loader id which defines which volume loader to use
const ctVolumeName = 'CT_VOLUME_ID'; // Id of the volume less loader prefix
const volumeId = `${volumeLoaderScheme}:${ctVolumeName}`; // VolumeId with loader id + volume id

export const runVolume = async (
  cornerstone3D,
  cornerstone3DTools,
  imageId,
  caseId,
  viewerRef1,
  viewerRef2,
  viewerRef3
) => {

  const {
    CONSTANTS, RenderingEngine, setVolumesForViewports, volumeLoader, metaData
  } = cornerstone3D;
  const {
    ToolGroupManager, StackScrollMouseWheelTool, CrosshairsTool, Enums: csToolsEnums, WindowLevelTool, PanTool, ZoomTool
  } = cornerstone3DTools;
  
  const { MouseBindings } = csToolsEnums;
  const { ViewportType } = cornerstone3D.Enums;
  const { ORIENTATION } = CONSTANTS;
  const toolGroupId = 'TOOLGROUP_ID';



  await initProviders();
  await initCornerstoneWADOImageLoader()
  await initVolumeLoader()
  await cornerstone3D.init();
  await cornerstone3DTools.init();




  const imageIds = await createImageIdsAndCacheMetaData({
    StudyInstanceUID: caseId,
    SeriesInstanceUID: imageId,
    wadoRsRoot: process.env.REACT_APP_WADO_RS_ROOT,
    type: 'VOLUME',
  });


  // Define a volume in memory
  const volume = await volumeLoader.createAndCacheVolume(volumeId, {
    imageIds,
  });

  // Instantiate a rendering engine
  const renderingEngineId = 'myRenderingEngine';
  const renderingEngine = new RenderingEngine(renderingEngineId);

  // Create the viewports
  if (
    viewerRef1.current && viewerRef2.current && viewerRef3.current
  ) {
    const viewportInputArray = [
      {
        viewportId: viewportId1,
        type: ViewportType.ORTHOGRAPHIC,
        element: viewerRef1.current,
        defaultOptions: {
          orientation: ORIENTATION.AXIAL,
          background: [0, 0, 0],
        },
      },
      {
        viewportId: viewportId2,
        type: ViewportType.ORTHOGRAPHIC,
        element: viewerRef2.current,
        defaultOptions: {
          orientation: ORIENTATION.SAGITTAL,
          background: [0, 0, 0],
        },
      },
      {
        viewportId: viewportId3,
        type: ViewportType.ORTHOGRAPHIC,
        element: viewerRef3.current,
        defaultOptions: {
          orientation: ORIENTATION.CORONAL,
          background: [0, 0, 0],
        },
      },
    ];
  
    renderingEngine.setViewports(viewportInputArray);
  }


  // Set the volume to load
  volume.load();

  // Set volumes on the viewports
  await setVolumesForViewports(
    renderingEngine,
    [
      {
        volumeId,
        callback: setCtTransferFunctionForVolumeActor,
      },
    ],
    [viewportId1, viewportId2, viewportId3]
  );

  
  let toolGroup = ToolGroupManager.getToolGroup(toolGroupId);
  if (!toolGroup) { 
    toolGroup =  ToolGroupManager.createToolGroup(toolGroupId); 
  }
  // For the crosshairs to operate, the viewports must currently be
  // added ahead of setting the tool active. This will be improved in the future.
  toolGroup.addViewport(viewportId1, renderingEngineId);
  toolGroup.addViewport(viewportId2, renderingEngineId);
  toolGroup.addViewport(viewportId3, renderingEngineId);

  // Manipulation Tools
  toolGroup.addTool(StackScrollMouseWheelTool.toolName);
  toolGroup.addTool(WindowLevelTool.toolName);
  toolGroup.addTool(PanTool.toolName);
  toolGroup.addTool(ZoomTool.toolName);

  // Add Crosshairs tool and configure it to link the three viewports
  // These viewports could use different tool groups. See the PET-CT example
  // for a more complicated used case.
  toolGroup.addTool(CrosshairsTool.toolName, {
    getReferenceLineColor,
    getReferenceLineControllable,
    getReferenceLineDraggableRotatable,
    getReferenceLineSlabThicknessControlsOn,
  });

  toolGroup?.setToolActive(CrosshairsTool.toolName, {
    bindings: [{ mouseButton: MouseBindings.Primary }],
  });
  // As the Stack Scroll mouse wheel is a tool using the `mouseWheelCallback`
  // hook instead of mouse buttons, it does not need to assign any mouse button.
  toolGroup?.setToolActive(StackScrollMouseWheelTool.toolName);

  // Render the image
  await renderingEngine.renderViewports([viewportId1, viewportId2, viewportId3]);
}

@JamesAPetts
Copy link
Member

I mean I want to display local dicom files by using wadouri prefix, not wadors , is there any way to get these UID?(studyInstanceUID, seriesInstanceUID)

WADO-URI or just "DICOM Part 10 over HTTP" isn't supported out the of box by the Cornerstone3D libraries.

You need to use a WADO-RS compliant endpoint to fetch the metadata ahead of time, and then WADO-RS retrieve frames for the URLs.

Or you could write your own loader for all of this, but its not recommended for MPR for the reasons outlined here.

@Jerome8780
Copy link

@zixiCat> 我认为您可能不会将元数据添加到基石WADOImageLoader中。

@zixiCat
I think you may not add the metadata into the cornerstoneWADOImageLoader.

我们应该怎么去加载呢?可以提供一个例子吗?感谢

@sedghi sedghi closed this as completed Oct 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants