Copying a volume's scalar type

How do I copy just the image information from a Scalar Volume Node “originalNode” to a new node initialized by newnode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLScalarVolumeNode')?

The problem with newnode.Copy(originalNode) is that it also copies the Scalar Type, which is too finicky to change, and it seems to round down the Image Origin and has an extra decimal place in Image Spacing. This causes the sequence to only store as a “Medical Reality Bundle” when I want it to save as a .seq.nrrd file.

I committed a temporary fix where it still registers with the fixed and moving volume being the same, but it is a little time consuming.

Image geometry (origin, spacing, axis directions) are stored in the IJK to RAS (voxel to physical space transformation) matrix. You can copy that information like this:

ijkToRas = vtk.vtkMatrix4x4()
sourceVolume.GetIJKToRASMatrix(ijkToRas)
targetVolume.SetIJKToRASMatrix(ijkToRas)

Thanks, then what do I do to copy the signal intensities over without copying the scalar type?

The problem seems to be that Elastix does not set IJKToRAS matrix of the resampled moving volume accurately. We should confirm this and report to Elastix developers, but until then we can apply the workaround of overwriting IJKToRAS of all the registered volumes to be exactly the same as the fixed volume’s IJKToRAS.

Does Elastix change the scalar type as well? If yes, then the simplest solution is probably to use vtkImageCast filter to set it to the same as the fixed volume’s scalar type.

Yes, Elastix changes the scalar type.

Would this be any faster than registering the fixed volume with itself?

Yes, copying and casting a volume is much faster. Do not register a volume to itself, as the result may not be always identical.

Thank you, how do I copy and cast the volume inputvol with scalar type int to outputvol with scalar type short?

VolNode->GetImageData() => cast filter => VolNode->SetAndObserveImageData()

Thank you, here is the full code for anyone wanting to change the scalar volume type of a volume node volumeNode:

imageCast = vtk.vtkImageCast()
imageCast.SetInputData(volumeNode.GetImageData())
# This could be substituted by SetOutputScalarTypeToX where X is the desired type
imageCast.SetOutputScalarTypeToShort()
imageCast.Update()
volumeNode.SetAndObserveImageData(imageCast.GetOutput())
4 Likes