Uploading a Volume from scratch, but too large a volume causes a crash

Hello, I’ve been working on writing a code to read in Seiman’s format PET and CT scans, and I’ve got the majority of the code written. Currently, it reads in PET images with no issues, and I can adjust and view them. However, when I try to load in a CT data set, which is much larger (496x496x496 as opposed to 128x128x159), A couple lines in the code cause my program to crash.

I load in the file as a numpy array and then use a slightly adjusted code I found in the forums by Csaba, which I’ll paste below:
importer = vtk.vtkImageImport()

    importer.CopyImportVoidPointer(img, img.nbytes)
    setDataType = 'importer.SetDataScalarTypeTo' + 'Float' + '()'
    eval(setDataType)
    importer.SetNumberOfScalarComponents(1)
    importer.SetWholeExtent(0,img.shape[0]-1,0,img.shape[1]-1,0,img.shape[2]-1)
    importer.SetDataExtentToWholeExtent()
    importer.Update()
    volume = slicer.vtkMRMLScalarVolumeNode()
    volume.SetName("image")
    volume.SetAndObserveImageData(importer.GetOutput())
    slicer.mrmlScene.AddNode(volume)
    volumeDisplayNode = 0
    volumeDisplayNode = slicer.vtkMRMLScalarVolumeDisplayNode()
    slicer.mrmlScene.AddNode(volumeDisplayNode)
    greyColorTable = slicer.util.getNode('Grey')
    volumeDisplayNode.SetAndObserveColorNodeID(greyColorTable.GetID())

    volume.SetAndObserveDisplayNodeID(volumeDisplayNode.GetID())
    volume.SetSpacing(xrat,yrat,zrat)
    selectionNode = slicer.app.applicationLogic().GetSelectionNode()
    selectionNode.SetReferenceActiveVolumeID(volume.GetID())
    slicer.app.applicationLogic().PropagateVolumeSelection(0)

Via trial and error I’ve isolated the two lines that cause the crash as:

    volume.SetAndObserveDisplayNodeID(volumeDisplayNode.GetID())

and

    slicer.app.applicationLogic().PropagateVolumeSelection(0)

Obviously (or maybe not, I’m not sure), without these two lines the image doesn’t show, but nor does it crash. I don’t personally know too much about slicer, but have experience programming in python. Is there another way I can represent the data so that it doesn’t take up too much space so slicer can read it? Alternatively, is there another function I can use to cause slicer to display the volume. Any advice would be appreciated! Thanks!

Hi @Troy -

Using void pointers can be crash-prone if you don’t have the datatypes or sizes just right.

Probably better to work with numpy arrays - you can see an example of creating a volume node and filling it with a numpy array here:

https://www.slicer.org/wiki/Documentation/Nightly/Developers/Python_scripting#Accessing_Volume_data_as_numpy_array

(BTW, are the PET and CT not in DICOM? Typically the DICOM data would load without needing a custom script. Memory shouldn’t be an issue for most scans and computers).

HTH,
Steve

Hi Steve,

These particular files aren’t DICOM, to convert it there’s an extra step that I’m trying to circumvent by writing this. And I start by creating numpy arrays, and then change those arrays in the above code. Is there an easier way to display and work with numpy arrays than that code? Sorry, I’m new to a lot of the libraries for Slicer

Yes, here is the code from the page I linked above - it creates a scalar volume node and displays it. Much simpler :smile: :

import numpy as np
import math

def some_func(x, y, z):
  return 0.5*x*x + 0.3*y*y + 0.5*z*z

a = np.fromfunction(some_func,(30,20,15))

volumeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode')
volumeNode.CreateDefaultDisplayNodes()
updateVolumeFromArray(volumeNode, a)
setSliceViewerLayers(background=volumeNode)

Perfect, that worked great! Thank you!