def loadBabies(self,directoryPath,pattern,maxIndex=None): self.images = [] filePaths = [] index = 1 import os.path while True: filePath = os.path.join(directoryPath, pattern % index) if not os.path.exists(filePath): break filePaths.append(filePath) index += 1 if maxIndex and index > maxIndex: break if len(filePaths) == 0: return middleBabyPath = filePaths[len(filePaths)/2] babyVolume = self.babyVolume(middleBabyPath) #transtor = slicer.vtkMRMLTransformStorageNode() reader = reader = vtkITK.vtkITKArchetypeImageSeriesScalarReader() reader.SetSingleFile(1) reader.SetUseOrientationFromFile(1) #reader.SetDesiredCoordinateOrientationToAxial() reader.SetOutputScalarTypeToNative() reader.SetUseNativeOriginOn() changeInfo = vtk.vtkImageChangeInformation() changeInfo.SetInputConnection( reader.GetOutputPort() ) changeInfo.SetOutputSpacing( 1, 1, 1 ) changeInfo.SetOutputOrigin( 0, 0, 0 ) self.images = {} self.rasToIJKs = {} #self.toTemplate = {} for filePath in filePaths: print("Loading %s" % filePath) reader.SetArchetype(filePath) changeInfo.Update() self.rasToIJKs[filePath] = vtk.vtkMatrix4x4() self.rasToIJKs[filePath].DeepCopy(reader.GetRasToIjkMatrix()) self.images[filePath] = vtk.vtkImageData() self.images[filePath].DeepCopy(changeInfo.GetOutput())
def read4DNIfTI(self, mvNode, fileName): """Try to read a 4D nifti file as a multivolume""" print('trying to read %s' % fileName) # use the vtk reader which seems to handle most nifti variants well reader = vtk.vtkNIFTIImageReader() reader.SetFileName(fileName) reader.SetTimeAsVector(True) reader.Update() header = reader.GetNIFTIHeader() qFormMatrix = reader.GetQFormMatrix() if not qFormMatrix: print('Warning: %s does not have a QFormMatrix - using Identity') qFormMatrix = vtk.vtkMatrix4x4() spacing = reader.GetOutputDataObject(0).GetSpacing() timeSpacing = reader.GetTimeSpacing() nFrames = reader.GetTimeDimension() if header.GetIntentCode() != header.IntentTimeSeries: intentName = header.GetIntentName() if not intentName: intentName = 'Nothing' print( f'Warning: {fileName} does not have TimeSeries intent, instead it has \"{intentName}\"' ) print('Trying to read as TimeSeries anyway') units = header.GetXYZTUnits() # try to account for some of the unit options # (Note: no test data available but we hope these are right) if units & header.UnitsMSec == header.UnitsMSec: timeSpacing /= 1000. if units & header.UnitsUSec == header.UnitsUSec: timeSpacing /= 1000. / 1000. spaceScaling = 1. if units & header.UnitsMeter == header.UnitsMeter: spaceScaling *= 1000. if units & header.UnitsMicron == header.UnitsMicron: spaceScaling /= 1000. spacing = [e * spaceScaling for e in spacing] # create frame labels using the timing info from the file # but use the advanced info so user can specify offset and scale volumeLabels = vtk.vtkDoubleArray() volumeLabels.SetNumberOfTuples(nFrames) frameLabelsAttr = '' for i in range(nFrames): frameId = self.__veInitial.value + timeSpacing * self.__veStep.value * i volumeLabels.SetComponent(i, 0, frameId) frameLabelsAttr += str(frameId) + ',' frameLabelsAttr = frameLabelsAttr[:-1] # create the display node mvDisplayNode = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount() - 1) mvDisplayNode.SetDefaultColorMap() # spacing and origin are in the ijkToRAS, so clear them from image data imageChangeInformation = vtk.vtkImageChangeInformation() imageChangeInformation.SetInputConnection(reader.GetOutputPort()) imageChangeInformation.SetOutputSpacing(1, 1, 1) imageChangeInformation.SetOutputOrigin(0, 0, 0) imageChangeInformation.Update() # QForm includes directions and origin, but not spacing so add that # here by multiplying by a diagonal matrix with the spacing scaleMatrix = vtk.vtkMatrix4x4() for diag in range(3): scaleMatrix.SetElement(diag, diag, spacing[diag]) ijkToRAS = vtk.vtkMatrix4x4() ijkToRAS.DeepCopy(qFormMatrix) vtk.vtkMatrix4x4.Multiply4x4(ijkToRAS, scaleMatrix, ijkToRAS) mvNode.SetIJKToRASMatrix(ijkToRAS) mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData( imageChangeInformation.GetOutputDataObject(0)) mvNode.SetNumberOfFrames(nFrames) # set the labels and other attributes, then display the volume mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel.text) mvNode.SetAttribute('MultiVolume.FrameLabels', frameLabelsAttr) mvNode.SetAttribute('MultiVolume.NumberOfFrames', str(nFrames)) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagName', '') mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits', '') mvNode.SetName(str(nFrames) + ' frames NIfTI MultiVolume') Helper.SetBgFgVolumes(mvNode.GetID(), None)
def extractROI(originalVolumeID, newVolumeID, rasCoordinates, diameter): ''' ''' originalVolume = slicer.mrmlScene.GetNodeByID(originalVolumeID) newVolume = slicer.mrmlScene.GetNodeByID(newVolumeID) # code below converted from cropVolume module by A. Fedorov # optimized after that :) inputRASToIJK = vtk.vtkMatrix4x4() inputIJKToRAS = vtk.vtkMatrix4x4() outputIJKToRAS = vtk.vtkMatrix4x4() outputRASToIJK = vtk.vtkMatrix4x4() volumeXform = vtk.vtkMatrix4x4() T = vtk.vtkMatrix4x4() originalVolume.GetRASToIJKMatrix(inputRASToIJK) originalVolume.GetIJKToRASMatrix(inputIJKToRAS) outputIJKToRAS.Identity() outputRASToIJK.Identity() volumeXform.Identity() T.Identity() # if the originalVolume is under a transform volumeTransformNode = originalVolume.GetParentTransformNode() if volumeTransformNode: volumeTransformNode.GetMatrixTransformToWorld(volumeXform) volumeXform.Invert() maxSpacing = max(originalVolume.GetSpacing()) # build our box rX = diameter * 4 * maxSpacing rY = diameter * 4 * maxSpacing rZ = diameter * 4 * maxSpacing cX = rasCoordinates[0] cY = rasCoordinates[1] cZ = rasCoordinates[2] inputSpacingX = originalVolume.GetSpacing()[0] inputSpacingY = originalVolume.GetSpacing()[1] inputSpacingZ = originalVolume.GetSpacing()[2] outputExtentX = int(2.0 * rX / inputSpacingX) outputExtentY = int(2.0 * rY / inputSpacingY) outputExtentZ = int(2.0 * rZ / inputSpacingZ) # configure spacing outputIJKToRAS.SetElement(0, 0, inputSpacingX) outputIJKToRAS.SetElement(1, 1, inputSpacingY) outputIJKToRAS.SetElement(2, 2, inputSpacingZ) # configure origin outputIJKToRAS.SetElement(0, 3, (cX - rX + inputSpacingX * 0.5)) outputIJKToRAS.SetElement(1, 3, (cY - rY + inputSpacingY * 0.5)) outputIJKToRAS.SetElement(2, 3, (cZ - rZ + inputSpacingZ * 0.5)) outputRASToIJK.DeepCopy(outputIJKToRAS) outputRASToIJK.Invert() T.DeepCopy(outputIJKToRAS) T.Multiply4x4(volumeXform, T, T) T.Multiply4x4(inputRASToIJK, T, T) resliceT = vtk.vtkTransform() resliceT.SetMatrix(T) reslicer = vtk.vtkImageReslice() reslicer.SetInterpolationModeToLinear() reslicer.SetInput(originalVolume.GetImageData()) reslicer.SetOutputExtent(0, int(outputExtentX), 0, int(outputExtentY), 0, int(outputExtentZ)) reslicer.SetOutputOrigin(0, 0, 0) reslicer.SetOutputSpacing(1, 1, 1) #reslicer.SetOutputOrigin(image.GetOrigin()) #reslicer.SetOutputSpacing(image.GetSpacing()) reslicer.SetResliceTransform(resliceT) reslicer.UpdateWholeExtent() changer = vtk.vtkImageChangeInformation() changer.SetInput(reslicer.GetOutput()) changer.SetOutputOrigin(0, 0, 0) changer.SetOutputSpacing(1, 1, 1) #changer.SetOutputOrigin(image.GetOrigin()) # changer.SetOutputSpacing(image.GetSpacing()) changer.Update() outImageData = vtk.vtkImageData() outImageData.DeepCopy(changer.GetOutput()) outImageData.Update() newVolume.SetAndObserveImageData(outImageData) newVolume.SetIJKToRASMatrix(outputIJKToRAS) newVolume.SetRASToIJKMatrix(outputRASToIJK) newVolume.Modified() newVolume.SetModifiedSinceRead(1)
def read4DNIfTI(self, mvNode, fileName): """Try to read a 4D nifti file as a multivolume""" print('trying to read %s' % fileName) # use the vtk reader which seems to handle most nifti variants well reader = vtk.vtkNIFTIImageReader() reader.SetFileName(fileName) reader.SetTimeAsVector(True) reader.Update() header = reader.GetNIFTIHeader() qFormMatrix = reader.GetQFormMatrix() if not qFormMatrix: print('Warning: %s does not have a QFormMatrix - using Identity') qFormMatrix = vtk.vtkMatrix4x4() spacing = reader.GetOutputDataObject(0).GetSpacing() timeSpacing = reader.GetTimeSpacing() nFrames = reader.GetTimeDimension() if header.GetIntentCode() != header.IntentTimeSeries: intentName = header.GetIntentName() if not intentName: intentName = 'Nothing' print('Warning: %s does not have TimeSeries intent, instead it has \"%s\"' % (fileName,intentName)) print('Trying to read as TimeSeries anyway') units = header.GetXYZTUnits() # try to account for some of the unit options # (Note: no test data available but we hope these are right) if units & header.UnitsMSec: timeSpacing /= 1000. if units & header.UnitsUSec: timeSpacing /= 1000. / 1000. spaceScaling = 1. if units & header.UnitsMeter: spaceScaling *= 1000. if units & header.UnitsMicron: spaceScaling /= 1000. spacing = map(lambda e: e * spaceScaling, spacing) # create frame labels using the timing info from the file # but use the advanced info so user can specify offset and scale volumeLabels = vtk.vtkDoubleArray() volumeLabels.SetNumberOfTuples(nFrames) frameLabelsAttr = '' for i in range(nFrames): frameId = self.__veInitial.value + timeSpacing * self.__veStep.value * i volumeLabels.SetComponent(i, 0, frameId) frameLabelsAttr += str(frameId)+',' frameLabelsAttr = frameLabelsAttr[:-1] # create the display node mvDisplayNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLMultiVolumeDisplayNode') mvDisplayNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(mvDisplayNode) mvDisplayNode.SetReferenceCount(mvDisplayNode.GetReferenceCount()-1) mvDisplayNode.SetDefaultColorMap() # spacing and origin are in the ijkToRAS, so clear them from image data imageChangeInformation = vtk.vtkImageChangeInformation() imageChangeInformation.SetInputConnection(reader.GetOutputPort()) imageChangeInformation.SetOutputSpacing( 1, 1, 1 ) imageChangeInformation.SetOutputOrigin( 0, 0, 0 ) imageChangeInformation.Update() # QForm includes directions and origin, but not spacing so add that # here by multiplying by a diagonal matrix with the spacing scaleMatrix = vtk.vtkMatrix4x4() for diag in range(3): scaleMatrix.SetElement(diag, diag, spacing[diag]) ijkToRAS = vtk.vtkMatrix4x4() ijkToRAS.DeepCopy(qFormMatrix) vtk.vtkMatrix4x4.Multiply4x4(ijkToRAS, scaleMatrix, ijkToRAS) mvNode.SetIJKToRASMatrix(ijkToRAS) mvNode.SetAndObserveDisplayNodeID(mvDisplayNode.GetID()) mvNode.SetAndObserveImageData(imageChangeInformation.GetOutputDataObject(0)) mvNode.SetNumberOfFrames(nFrames) # set the labels and other attributes, then display the volume mvNode.SetLabelArray(volumeLabels) mvNode.SetLabelName(self.__veLabel.text) mvNode.SetAttribute('MultiVolume.FrameLabels',frameLabelsAttr) mvNode.SetAttribute('MultiVolume.NumberOfFrames',str(nFrames)) mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagName','') mvNode.SetAttribute('MultiVolume.FrameIdentifyingDICOMTagUnits','') mvNode.SetName(str(nFrames)+' frames NIfTI MultiVolume') Helper.SetBgFgVolumes(mvNode.GetID(),None)
def extractROI(originalVolumeID,newVolumeID,rasCoordinates,diameter): ''' ''' originalVolume = slicer.mrmlScene.GetNodeByID(originalVolumeID) newVolume = slicer.mrmlScene.GetNodeByID(newVolumeID) # code below converted from cropVolume module by A. Fedorov # optimized after that :) inputRASToIJK = vtk.vtkMatrix4x4() inputIJKToRAS = vtk.vtkMatrix4x4() outputIJKToRAS = vtk.vtkMatrix4x4() outputRASToIJK = vtk.vtkMatrix4x4() volumeXform = vtk.vtkMatrix4x4() T = vtk.vtkMatrix4x4() originalVolume.GetRASToIJKMatrix(inputRASToIJK) originalVolume.GetIJKToRASMatrix(inputIJKToRAS) outputIJKToRAS.Identity() outputRASToIJK.Identity() volumeXform.Identity() T.Identity() # if the originalVolume is under a transform volumeTransformNode = originalVolume.GetParentTransformNode() if volumeTransformNode: volumeTransformNode.GetMatrixTransformToWorld(volumeXform) volumeXform.Invert() maxSpacing = max(originalVolume.GetSpacing()) # build our box rX = diameter*4*maxSpacing rY = diameter*4*maxSpacing rZ = diameter*4*maxSpacing cX = rasCoordinates[0] cY = rasCoordinates[1] cZ = rasCoordinates[2] inputSpacingX = originalVolume.GetSpacing()[0] inputSpacingY = originalVolume.GetSpacing()[1] inputSpacingZ = originalVolume.GetSpacing()[2] outputExtentX = int(2.0*rX/inputSpacingX) outputExtentY = int(2.0*rY/inputSpacingY) outputExtentZ = int(2.0*rZ/inputSpacingZ) # configure spacing outputIJKToRAS.SetElement(0,0,inputSpacingX) outputIJKToRAS.SetElement(1,1,inputSpacingY) outputIJKToRAS.SetElement(2,2,inputSpacingZ) # configure origin outputIJKToRAS.SetElement(0,3,(cX-rX+inputSpacingX*0.5)) outputIJKToRAS.SetElement(1,3,(cY-rY+inputSpacingY*0.5)) outputIJKToRAS.SetElement(2,3,(cZ-rZ+inputSpacingZ*0.5)) outputRASToIJK.DeepCopy(outputIJKToRAS) outputRASToIJK.Invert() T.DeepCopy(outputIJKToRAS) T.Multiply4x4(volumeXform,T,T) T.Multiply4x4(inputRASToIJK,T,T) resliceT = vtk.vtkTransform() resliceT.SetMatrix(T) reslicer = vtk.vtkImageReslice() reslicer.SetInterpolationModeToLinear() reslicer.SetInput(originalVolume.GetImageData()) reslicer.SetOutputExtent(0,int(outputExtentX),0,int(outputExtentY),0,int(outputExtentZ)) reslicer.SetOutputOrigin(0,0,0) reslicer.SetOutputSpacing(1,1,1) #reslicer.SetOutputOrigin(image.GetOrigin()) #reslicer.SetOutputSpacing(image.GetSpacing()) reslicer.SetResliceTransform(resliceT) reslicer.UpdateWholeExtent() changer = vtk.vtkImageChangeInformation() changer.SetInput(reslicer.GetOutput()) changer.SetOutputOrigin(0,0,0) changer.SetOutputSpacing(1,1,1) #changer.SetOutputOrigin(image.GetOrigin()) # changer.SetOutputSpacing(image.GetSpacing()) changer.Update() outImageData = vtk.vtkImageData() outImageData.DeepCopy(changer.GetOutput()) outImageData.Update() newVolume.SetAndObserveImageData(outImageData) newVolume.SetIJKToRASMatrix(outputIJKToRAS) newVolume.SetRASToIJKMatrix(outputRASToIJK) newVolume.Modified()