def loadImageData(self, filePath, grayscale, volumeNode): import vtkITK if grayscale: reader = vtkITK.vtkITKArchetypeImageSeriesScalarReader() else: reader = vtkITK.vtkITKArchetypeImageSeriesVectorReaderFile() reader.SetArchetype(filePath) reader.AddFileName(filePath) reader.SetSingleFile(True) reader.SetOutputScalarTypeToNative() reader.SetDesiredCoordinateOrientationToNative() reader.SetUseNativeOriginOn() # GDCM is not particularly better in this than DCMTK, we just select one explicitly # so that we know which one is used reader.SetDICOMImageIOApproachToGDCM() reader.Update() if reader.GetErrorCode() != vtk.vtkErrorCode.NoError: errorString = vtk.vtkErrorCode.GetStringFromErrorCode( reader.GetErrorCode()) raise ValueError( f"Could not read image {loadable.name} from file {filePath}. Error is: {errorString}" ) rasToIjk = reader.GetRasToIjkMatrix() ijkToRas = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Invert(rasToIjk, ijkToRas) return reader.GetOutput(), ijkToRas
def load(self, loadable): """Load the selection """ if loadable.grayscale: volumeNode = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLScalarVolumeNode", loadable.name) else: volumeNode = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLVectorVolumeNode", loadable.name) import vtkITK if loadable.grayscale: reader = vtkITK.vtkITKArchetypeImageSeriesScalarReader() else: reader = vtkITK.vtkITKArchetypeImageSeriesVectorReaderFile() filePath = loadable.files[0] reader.SetArchetype(filePath) reader.AddFileName(filePath) reader.SetSingleFile(True) reader.SetOutputScalarTypeToNative() reader.SetDesiredCoordinateOrientationToNative() reader.SetUseNativeOriginOn() # GDCM is not particularly better in this than DCMTK, we just select one explicitly # so that we know which one is used reader.SetDICOMImageIOApproachToGDCM() reader.Update() if reader.GetErrorCode() != vtk.vtkErrorCode.NoError: errorString = vtk.vtkErrorCode.GetStringFromErrorCode( reader.GetErrorCode()) raise ValueError( f"Could not read image {loadable.name} from file {filePath}. Error is: {errorString}" ) rasToIjk = reader.GetRasToIjkMatrix() ijkToRas = vtk.vtkMatrix4x4() vtk.vtkMatrix4x4.Invert(rasToIjk, ijkToRas) imageData = reader.GetOutput() imageData.SetSpacing(1.0, 1.0, 1.0) imageData.SetOrigin(0.0, 0.0, 0.0) volumeNode.SetIJKToRASMatrix(ijkToRas) volumeNode.SetAndObserveImageData(imageData) # show volume appLogic = slicer.app.applicationLogic() selNode = appLogic.GetSelectionNode() selNode.SetActiveVolumeID(volumeNode.GetID()) appLogic.PropagateVolumeSelection() return volumeNode
def loadFilesWithSeriesReader(self,imageIOName,files,name,grayscale=True): """ Explicitly use the named imageIO to perform the loading """ if grayscale: reader = vtkITK.vtkITKArchetypeImageSeriesScalarReader() else: reader = vtkITK.vtkITKArchetypeImageSeriesVectorReaderFile() reader.SetArchetype(files[0]) for f in files: reader.AddFileName(f) reader.SetSingleFile(0) reader.SetOutputScalarTypeToNative() reader.SetDesiredCoordinateOrientationToNative() reader.SetUseNativeOriginOn() if imageIOName == "GDCM": reader.SetDICOMImageIOApproachToGDCM() elif imageIOName == "DCMTK": reader.SetDICOMImageIOApproachToDCMTK() else: raise Exception("Invalid imageIOName of %s" % imageIOName) logging.info("Loading with imageIOName: %s" % imageIOName) reader.Update() slicer.modules.reader = reader if reader.GetErrorCode() != vtk.vtkErrorCode.NoError: errorStrings = (imageIOName, vtk.vtkErrorCode.GetStringFromErrorCode(reader.GetErrorCode())) logging.error("Could not read scalar volume using %s approach. Error is: %s" % errorStrings) return imageChangeInformation = vtk.vtkImageChangeInformation() imageChangeInformation.SetInputConnection(reader.GetOutputPort()) imageChangeInformation.SetOutputSpacing( 1, 1, 1 ) imageChangeInformation.SetOutputOrigin( 0, 0, 0 ) imageChangeInformation.Update() name = slicer.mrmlScene.GenerateUniqueName(name) if grayscale: volumeNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode", name) else: volumeNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLVectorVolumeNode", name) volumeNode.SetAndObserveImageData(imageChangeInformation.GetOutputDataObject(0)) slicer.vtkMRMLVolumeArchetypeStorageNode.SetMetaDataDictionaryFromReader(volumeNode, reader) volumeNode.SetRASToIJKMatrix(reader.GetRasToIjkMatrix()) volumeNode.CreateDefaultDisplayNodes() slicer.modules.DICOMInstance.reader = reader slicer.modules.DICOMInstance.imageChangeInformation = imageChangeInformation return(volumeNode)
def load(self,loadable): """Load the selection """ outputSequenceNodes = [] for filePath in loadable.files: import vtkITK if loadable.grayscale: reader = vtkITK.vtkITKArchetypeImageSeriesScalarReader() else: reader = vtkITK.vtkITKArchetypeImageSeriesVectorReaderFile() reader.SetArchetype(filePath) reader.AddFileName(filePath) reader.SetSingleFile(True) reader.SetOutputScalarTypeToNative() reader.SetDesiredCoordinateOrientationToNative() reader.SetUseNativeOriginOn() # GDCM is not particularly better in this than DCMTK, we just select one explicitly # so that we know which one is used reader.SetDICOMImageIOApproachToGDCM() reader.Update() if reader.GetErrorCode() != vtk.vtkErrorCode.NoError: errorString = vtk.vtkErrorCode.GetStringFromErrorCode(reader.GetErrorCode()) raise ValueError("Could not read image {0} from file {1}. Error is: {2}".format(loadable.name, filePath, errorString)) volume = reader.GetOutput() [spacingX, spacingY, frameTimeMsec] = volume.GetSpacing() volume.SetSpacing(1.0, 1.0, 1.0) outputSequenceNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLSequenceNode") if frameTimeMsec == 1.0: # frame time is not found, set it to 1.0fps frameTime = 1 outputSequenceNode.SetIndexName("frame") outputSequenceNode.SetIndexUnit("") playbackRateFps = 10 else: frameTime = frameTimeMsec * 0.001 outputSequenceNode.SetIndexName("time") outputSequenceNode.SetIndexUnit("s") playbackRateFps = 1.0/frameTime if loadable.grayscale: tempFrameVolume = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode") else: tempFrameVolume = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLVectorVolumeNode") # Rotate 180deg, otherwise the image would appear upside down ijkToRAS = vtk.vtkMatrix4x4() ijkToRAS.SetElement(0,0,-1.0) ijkToRAS.SetElement(1,1,-1.0) tempFrameVolume.SetIJKToRASMatrix(ijkToRAS) tempFrameVolume.SetSpacing(spacingX, spacingY, 1.0) numberOfFrames = volume.GetDimensions()[2] extent = volume.GetExtent() numberOfFrames = extent[5]-extent[4]+1 for frame in range(numberOfFrames): crop = vtk.vtkImageClip() crop.SetInputData(volume) crop.SetOutputWholeExtent(extent[0], extent[1], extent[2], extent[3], extent[4]+frame, extent[4]+frame) crop.ClipDataOn() crop.Update() croppedOutput = crop.GetOutput() croppedOutput.SetExtent(extent[0], extent[1], extent[2], extent[3], 0, 0) tempFrameVolume.SetAndObserveImageData(croppedOutput) if type(frameTime)==int: timeStampSec = str(frame * frameTime) else: timeStampSec = "{:.3f}".format(frame * frameTime) outputSequenceNode.SetDataNodeAtValue(tempFrameVolume, timeStampSec) slicer.mrmlScene.RemoveNode(tempFrameVolume) if len(loadable.files) == 1: outputSequenceNode.SetName(loadable.name) else: ds = dicom.read_file(filePath, stop_before_pixels=True) if hasattr(ds, 'PositionerPrimaryAngle') and hasattr(ds, 'PositionerSecondaryAngle'): outputSequenceNode.SetName('{0} ({1}/{2})'.format(loadable.name, ds.PositionerPrimaryAngle,ds.PositionerSecondaryAngle)) else: outputSequenceNode.SetName(loadable.name) slicer.mrmlScene.AddNode(outputSequenceNode) # Create storage node that allows saving node as nrrd outputSequenceStorageNode = slicer.vtkMRMLVolumeSequenceStorageNode() slicer.mrmlScene.AddNode(outputSequenceStorageNode) outputSequenceNode.SetAndObserveStorageNodeID(outputSequenceStorageNode.GetID()) outputSequenceNodes.append(outputSequenceNode) if not hasattr(loadable, 'createBrowserNode') or loadable.createBrowserNode: # Add a browser node and show the volume in the slice viewer for user convenience outputSequenceBrowserNode = slicer.vtkMRMLSequenceBrowserNode() outputSequenceBrowserNode.SetName(slicer.mrmlScene.GenerateUniqueName(loadable.name+' browser')) outputSequenceBrowserNode.SetPlaybackRateFps(playbackRateFps) slicer.mrmlScene.AddNode(outputSequenceBrowserNode) # Add all sequences to the sequence browser first = True for outputSequenceNode in outputSequenceNodes: #outputSequenceBrowserNode.SetAndObserveMasterSequenceNodeID(outputSequenceNode.GetID()) outputSequenceBrowserNode.AddSynchronizedSequenceNode(outputSequenceNode) proxyVolumeNode = outputSequenceBrowserNode.GetProxyNode(outputSequenceNode) # create Subject hierarchy nodes for the loaded series self.addSeriesInSubjectHierarchy(loadable, proxyVolumeNode) if first: first = False # Automatically select the volume to display appLogic = slicer.app.applicationLogic() selNode = appLogic.GetSelectionNode() selNode.SetReferenceActiveVolumeID(proxyVolumeNode.GetID()) appLogic.PropagateVolumeSelection() appLogic.FitSliceToAll() slicer.modules.sequences.setToolBarActiveBrowserNode(outputSequenceBrowserNode) # Show sequence browser toolbar slicer.modules.sequences.showSequenceBrowser(outputSequenceBrowserNode) return outputSequenceNode