示例#1
0
    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
示例#3
0
  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