Convert between MultiVolume and Volume Sequence?

OK, for the basic Sequence → MultiVolume conversion, saving individual volumes to a temporary folder and then using MultiVolume Importer works OK. However, for DSCMRIAnalysis to work properly, the MultiVolume needs to have some of the DICOM tags stored as attributes, and these are not collected in the loading as Sequence step. However, I can restore these by copying attribute values from the original MultiVolume (from before registration) to the registered MultiVolume. The attributes in the original are

>> mvOrig.GetAttributeNames()
('DICOM.instanceUIDs', 'MultiVolume.DICOM.EchoTime', 'MultiVolume.DICOM.FlipAngle', 'MultiVolume.DICOM.RepetitionTime', 'MultiVolume.FrameIdentifyingDICOMTagName', 'MultiVolume.FrameIdentifyingDICOMTagUnits', 'MultiVolume.FrameLabels', 'MultiVolume.NumberOfFrames', 'MultiVolume.ParseStrategy')

I think the key ones needed are the echo time, flip angle, and repetition time. Possibly also the frame labels (these are based on the repetition time in the original). It seems safe just to copy all of them over.

Final functional workflow goes as follows:

  1. Using DICOM browser, import perfusion series as a MultiVolume and as a VolumeSequence.
  2. Use Sequence Registration with the “rigid (all)” preset to register the sequence to a new Volume Sequence.
  3. Save the individual nodes in the registered volume sequence to individual .nrrd files in a temporary folder.
  4. Open MultiVolumeImporter and point it at the temporary folder and load as MultiVolume
  5. Copy the attribute values from the original MultiVolume (non-registered) to the new MultiVolume (registered).
  6. Run DSCMRIAnalysis on the registered MultiVolume.

Python for step 3:

import os
import os.path
outDir = os.path.join(slicer.app.temporaryPath, 'MyUniqSubDirectoryForOutput')
os.mkdir(outDir)
seqNode = getNode('vtkMRMLSequenceNode1') # use MRML ID of the loaded sequence
browserNode = slicer.modules.sequences.logic().GetFirstBrowserNodeForSequenceNode(seqNode)
for volNum in range(browserNode.GetNumberOfItems()):
    browserNode.SetSelectedItemNumber(volNum)
    volNode = browserNode.GetProxyNode(seqNode)
    saveName = 'Im%04d.nrrd' % volNum
    slicer.util.saveNode(volNode, os.path.join(outDir, saveName)

I found that you needed to use the browser node in the above code because slicer.util.saveNode(seqNode.GetNthDataNode(volNum), saveName) does not work because the internal data nodes of the sequence are not technically present in the MRML scene, only the current proxy node is, and therefore saveNode can’t find them to save and throws an error.

Python for step 5:

mvOrig = getNode('vtkMRMLMultiVolumeNode1') # use MRML ID for original MultiVolumeNode
mvReg = getNode('vtkMRMLMultiVolumeNode2') # use MRML ID for imported registered 
for attr in mvOrig.GetAttributeNames():
    mvReg.SetAttribute(attr, mvOrig.GetAttribute(attr))
1 Like