Esempio n. 1
0
    def addSequenceBrowserNode(self, name, outputSequenceNodes,
                               playbackRateFps, loadable):
        # Add a browser node and show the volume in the slice viewer for user convenience
        outputSequenceBrowserNode = slicer.vtkMRMLSequenceBrowserNode()
        outputSequenceBrowserNode.SetName(
            slicer.mrmlScene.GenerateUniqueName(name + ' browser'))
        outputSequenceBrowserNode.SetPlaybackRateFps(playbackRateFps)
        slicer.mrmlScene.AddNode(outputSequenceBrowserNode)

        # Add all sequences to the sequence browser
        first = True
        for outputSequenceNode in outputSequenceNodes:
            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)
  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
    def loadPhilips4DUSAsSequence(self, loadable):
        """Load the selection as an Ultrasound, store in a Sequence node
    """

        # get the key info from the "fake" dicom file
        filePath = loadable.files[0]
        ds = dicom.read_file(filePath, stop_before_pixels=True)
        columns = ds.Columns
        rows = ds.Rows
        slices = ds[(0x3001, 0x1001)].value  # private tag!
        spacing = (
            ds.PhysicalDeltaX * 10,
            ds.PhysicalDeltaY * 10,
            ds[(0x3001, 0x1003)].value * 10  # private tag!
        )
        frames = int(ds.NumberOfFrames)
        imageComponents = frames
        frameTimeMsec = ds.FrameTime

        pixelShape = (frames, slices, rows, columns)
        pixelSize = pixelShape[0] * pixelShape[1] * pixelShape[2] * pixelShape[
            3]
        totalFileSize = os.path.getsize(filePath)
        headerSize = totalFileSize - pixelSize

        outputSequenceNode = slicer.vtkMRMLSequenceNode()

        for frame in range(frames):

            imgReader = vtk.vtkImageReader()
            imgReader.SetFileDimensionality(3)
            imgReader.SetFileName(filePath)
            imgReader.SetNumberOfScalarComponents(1)
            imgReader.SetDataScalarTypeToUnsignedChar()
            imgReader.SetDataExtent(0, columns - 1, 0, rows - 1, 0, slices - 1)
            imgReader.SetHeaderSize(headerSize +
                                    frame * slices * rows * columns)
            imgReader.FileLowerLeftOn()
            imgReader.Update()

            outputNode = slicer.vtkMRMLScalarVolumeNode()
            outputNode.SetAndObserveImageData(imgReader.GetOutput())
            outputNode.SetSpacing(spacing)

            timeStampSec = "{:.3f}".format(frame * frameTimeMsec * 0.001)
            outputSequenceNode.SetDataNodeAtValue(outputNode, timeStampSec)

        outputSequenceNode.SetName(
            slicer.mrmlScene.GenerateUniqueName(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())

        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(
                    outputSequenceNode.GetName() + ' browser'))
            slicer.mrmlScene.AddNode(outputSequenceBrowserNode)
            outputSequenceBrowserNode.SetAndObserveMasterSequenceNodeID(
                outputSequenceNode.GetID())
            masterOutputNode = outputSequenceBrowserNode.GetProxyNode(
                outputSequenceNode)

            # Automatically select the volume to display
            appLogic = slicer.app.applicationLogic()
            selNode = appLogic.GetSelectionNode()
            selNode.SetReferenceActiveVolumeID(masterOutputNode.GetID())
            appLogic.PropagateVolumeSelection()
            appLogic.FitSliceToAll()
            slicer.modules.sequencebrowser.setToolBarActiveBrowserNode(
                outputSequenceBrowserNode)

            # create Subject hierarchy nodes for the loaded series
            self.addSeriesInSubjectHierarchy(loadable, masterOutputNode)

        return outputSequenceNode
  def loadAsSequence(self,loadable):
    """Load the selection as an Ultrasound, store in a Sequence node
    """

    # get the key info from the "fake" dicom file
    filePath = loadable.files[0]
    ds = dicom.read_file(filePath, stop_before_pixels=True)
    columns = ds.Columns
    rows = ds.Rows
    slices = ds[(0x3001,0x1001)].value # private tag!
    spacing = (
            ds.PhysicalDeltaX * 10,
            ds.PhysicalDeltaY * 10,
            ds[(0x3001,0x1003)].value * 10 # private tag!
            )
    frames  = int(ds.NumberOfFrames)
    imageComponents = frames
    frameTimeMsec = ds.FrameTime

    pixelShape = (frames, slices, rows, columns)
    pixelSize = reduce(lambda x,y : x*y, pixelShape)
    totalFileSize = os.path.getsize(filePath)
    headerSize = totalFileSize-pixelSize
    
    outputSequenceNode = slicer.vtkMRMLSequenceNode()
    
    for frame in range(frames):
    
      imgReader = vtk.vtkImageReader()
      imgReader.SetFileDimensionality(3)
      imgReader.SetFileName(filePath);
      imgReader.SetNumberOfScalarComponents(1)
      imgReader.SetDataScalarTypeToUnsignedChar()
      imgReader.SetDataExtent(0,columns-1, 0,rows-1, 0,slices-1)
      imgReader.SetHeaderSize(headerSize+frame*slices*rows*columns)
      imgReader.FileLowerLeftOn();
      imgReader.Update()
          
      outputNode = slicer.vtkMRMLScalarVolumeNode() 
      outputNode.SetAndObserveImageData(imgReader.GetOutput())
      outputNode.SetSpacing(spacing)

      timeStampSec = "{:.3f}".format(frame * frameTimeMsec * 0.001)
      outputSequenceNode.SetDataNodeAtValue(outputNode, timeStampSec)

    outputSequenceNode.SetName(slicer.mrmlScene.GenerateUniqueName(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())

    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(outputSequenceNode.GetName()+' browser'))
      slicer.mrmlScene.AddNode(outputSequenceBrowserNode)
      outputSequenceBrowserNode.SetAndObserveMasterSequenceNodeID(outputSequenceNode.GetID())
      masterOutputNode = outputSequenceBrowserNode.GetVirtualOutputDataNode(outputSequenceNode)
    
      # Automatically select the volume to display
      appLogic = slicer.app.applicationLogic()
      selNode = appLogic.GetSelectionNode()
      selNode.SetReferenceActiveVolumeID(masterOutputNode.GetID())
      appLogic.PropagateVolumeSelection()
      appLogic.FitSliceToAll()

      outputSequenceBrowserNode.ScalarVolumeAutoWindowLevelOff() # for performance optimization

      # create Subject hierarchy nodes for the loaded series
      self.addSeriesInSubjectHierarchy(loadable, masterOutputNode)

    return outputSequenceNode