Пример #1
0
        def gridTransformFromCorners(self, volumeNode, sourceCorners,
                                     targetCorners):
            """Create a grid transform that maps between the current and the desired corners.
      """
            # sanity check
            columns, rows, slices = volumeNode.GetImageData().GetDimensions()
            cornerShape = (slices, 2, 2, 3)
            if not (sourceCorners.shape == cornerShape
                    and targetCorners.shape == cornerShape):
                raise Exception(
                    "Corner shapes do not match volume dimensions %s, %s, %s" %
                    (sourceCorners.shape, targetCorners.shape, cornerShape))

            # create the grid transform node
            gridTransform = slicer.vtkMRMLGridTransformNode()
            gridTransform.SetName(
                slicer.mrmlScene.GenerateUniqueName(volumeNode.GetName() +
                                                    ' acquisition transform'))
            slicer.mrmlScene.AddNode(gridTransform)

            # place grid transform in the same subject hierarchy folder as the volume node
            shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(
                slicer.mrmlScene)
            volumeParentItemId = shNode.GetItemParent(
                shNode.GetItemByDataNode(volumeNode))
            shNode.SetItemParent(shNode.GetItemByDataNode(gridTransform),
                                 volumeParentItemId)

            # create a grid transform with one vector at the corner of each slice
            # the transform is in the same space and orientation as the volume node
            gridImage = vtk.vtkImageData()
            gridImage.SetOrigin(*volumeNode.GetOrigin())
            gridImage.SetDimensions(2, 2, slices)
            sourceSpacing = volumeNode.GetSpacing()
            gridImage.SetSpacing(sourceSpacing[0] * columns,
                                 sourceSpacing[1] * rows, sourceSpacing[2])
            gridImage.AllocateScalars(vtk.VTK_DOUBLE, 3)
            transform = slicer.vtkOrientedGridTransform()
            directionMatrix = vtk.vtkMatrix4x4()
            volumeNode.GetIJKToRASDirectionMatrix(directionMatrix)
            transform.SetGridDirectionMatrix(directionMatrix)
            transform.SetDisplacementGridData(gridImage)
            gridTransform.SetAndObserveTransformToParent(transform)
            volumeNode.SetAndObserveTransformNodeID(gridTransform.GetID())

            # populate the grid so that each corner of each slice
            # is mapped from the source corner to the target corner
            displacements = slicer.util.arrayFromGridTransform(gridTransform)
            for sliceIndex in range(slices):
                for row in range(2):
                    for column in range(2):
                        displacements[sliceIndex][row][column] = targetCorners[
                            sliceIndex][row][column] - sourceCorners[
                                sliceIndex][row][column]
    def onExportGrid(self):
        """Converts the current thin plate transform to a grid"""
        self.hotUpdateButton = None
        state = self.registrationState()

        # since the transform is ras-to-ras, we find the extreme points
        # in ras space of the fixed (target) volume and fix the unoriented
        # box around it.  Sample the grid transform at the resolution of
        # the fixed volume, which may be a bit overkill but it should aways
        # work without too much loss.
        rasBounds = [
            0,
        ] * 6
        state.fixed.GetRASBounds(rasBounds)
        from math import floor, ceil
        origin = list(map(int, map(floor, rasBounds[::2])))
        maxes = list(map(int, map(ceil, rasBounds[1::2])))
        boundSize = [m - o for m, o in zip(maxes, origin)]
        spacing = state.fixed.GetSpacing()
        samples = [ceil(int(b / s)) for b, s in zip(boundSize, spacing)]
        extent = [
            0,
        ] * 6
        extent[::2] = [
            0,
        ] * 3
        extent[1::2] = samples
        extent = list(map(int, extent))

        toGrid = vtk.vtkTransformToGrid()
        toGrid.SetGridOrigin(origin)
        toGrid.SetGridSpacing(state.fixed.GetSpacing())
        toGrid.SetGridExtent(extent)
        toGrid.SetInput(
            state.transform.GetTransformFromParent())  # same in VTKv 5 & 6
        toGrid.Update()

        gridTransform = slicer.vtkOrientedGridTransform()
        if vtk.VTK_MAJOR_VERSION < 6:
            gridTransform.SetDisplacementGrid(
                toGrid.GetOutput())  # different in VTKv 5 & 6
        else:
            gridTransform.SetDisplacementGridData(toGrid.GetOutput())
        gridNode = slicer.vtkMRMLGridTransformNode()
        gridNode.SetAndObserveTransformFromParent(gridTransform)
        gridNode.SetName(state.transform.GetName() + "-grid")
        slicer.mrmlScene.AddNode(gridNode)
Пример #3
0
    def gridTransformFromCorners(self,volumeNode,sourceCorners,targetCorners):
      """Create a grid transform that maps between the current and the desired corners.
      """
      # sanity check
      columns, rows, slices = volumeNode.GetImageData().GetDimensions()
      cornerShape = (slices, 2, 2, 3)
      if not (sourceCorners.shape == cornerShape and targetCorners.shape == cornerShape):
        raise Exception("Corner shapes do not match volume dimensions %s, %s, %s" %
                          (sourceCorners.shape, targetCorners.shape, cornerShape))

      # create the grid transform node
      gridTransform = slicer.vtkMRMLGridTransformNode()
      gridTransform.SetName(slicer.mrmlScene.GenerateUniqueName(volumeNode.GetName()+' acquisition transform'))
      slicer.mrmlScene.AddNode(gridTransform)

      # place grid transform in the same subject hierarchy folder as the volume node
      shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
      volumeParentItemId = shNode.GetItemParent(shNode.GetItemByDataNode(volumeNode))
      shNode.SetItemParent(shNode.GetItemByDataNode(gridTransform), volumeParentItemId)

      # create a grid transform with one vector at the corner of each slice
      # the transform is in the same space and orientation as the volume node
      gridImage = vtk.vtkImageData()
      gridImage.SetOrigin(*volumeNode.GetOrigin())
      gridImage.SetDimensions(2, 2, slices)
      sourceSpacing = volumeNode.GetSpacing()
      gridImage.SetSpacing(sourceSpacing[0] * columns, sourceSpacing[1] * rows, sourceSpacing[2])
      gridImage.AllocateScalars(vtk.VTK_DOUBLE, 3)
      transform = slicer.vtkOrientedGridTransform()
      directionMatrix = vtk.vtkMatrix4x4()
      volumeNode.GetIJKToRASDirectionMatrix(directionMatrix)
      transform.SetGridDirectionMatrix(directionMatrix)
      transform.SetDisplacementGridData(gridImage)
      gridTransform.SetAndObserveTransformToParent(transform)
      volumeNode.SetAndObserveTransformNodeID(gridTransform.GetID())

      # populate the grid so that each corner of each slice
      # is mapped from the source corner to the target corner
      displacements = slicer.util.arrayFromGridTransform(gridTransform)
      for sliceIndex in range(slices):
        for row in range(2):
          for column in range(2):
            displacements[sliceIndex][row][column] = targetCorners[sliceIndex][row][column] - sourceCorners[sliceIndex][row][column]
Пример #4
0
  def onExportGrid(self):
    """Converts the current thin plate transform to a grid"""
    state = self.registationState()

    # since the transform is ras-to-ras, we find the extreme points
    # in ras space of the fixed (target) volume and fix the unoriented
    # box around it.  Sample the grid transform at the resolution of
    # the fixed volume, which may be a bit overkill but it should aways
    # work without too much loss.
    rasBounds = [0,]*6
    state.fixed.GetRASBounds(rasBounds)
    from math import floor, ceil
    origin = map(int,map(floor,rasBounds[::2]))
    maxes = map(int,map(ceil,rasBounds[1::2]))
    boundSize = [m - o for m,o in zip(maxes,origin) ]
    spacing = state.fixed.GetSpacing()
    samples = [ceil(b / s) for b,s in zip(boundSize,spacing)]
    extent = [0,]*6
    extent[::2] = [0,]*3
    extent[1::2] = samples
    extent = map(int,extent)

    toGrid = vtk.vtkTransformToGrid()
    toGrid.SetGridOrigin(origin)
    toGrid.SetGridSpacing(state.fixed.GetSpacing())
    toGrid.SetGridExtent(extent)
    toGrid.SetInput(state.transform.GetTransformFromParent()) # same in VTKv 5 & 6
    toGrid.Update()

    gridTransform = vtk.vtkGridTransform()
    if vtk.VTK_MAJOR_VERSION < 6:
      gridTransform.SetDisplacementGrid(toGrid.GetOutput()) # different in VTKv 5 & 6
    else:
      gridTransform.SetDisplacementGridData(toGrid.GetOutput())
    gridNode = slicer.vtkMRMLGridTransformNode()
    gridNode.SetAndObserveTransformFromParent(gridTransform)
    gridNode.SetName(state.transform.GetName()+"-grid")
    slicer.mrmlScene.AddNode(gridNode)
Пример #5
0
    def createAcquisitionTransform(self, volumeNode, metadata):

        # Creates transform that applies scan conversion transform
        probeRadius = metadata['CurvatureRadiusProbe']
        trackRadius = metadata['CurvatureRadiusTrack']
        if trackRadius != 0.0:
            raise ValueError(f"Curvature Radius (Track) is {trackRadius}. Currently, only volume with zero radius can be imported.")

        # Create a sampling grid for the transform
        import numpy as np
        spacing = np.array(volumeNode.GetSpacing())
        averageSpacing = (spacing[0] + spacing[1] + spacing[2]) / 3.0
        voxelsPerTransformControlPoint = 20  # the transform is changing smoothly, so we don't need to add too many control points
        gridSpacingMm = averageSpacing * voxelsPerTransformControlPoint
        gridSpacingVoxel = np.floor(gridSpacingMm / spacing).astype(int)
        gridAxesIJK = []
        imageData = volumeNode.GetImageData()
        extent = imageData.GetExtent()
        for axis in range(3):
            gridAxesIJK.append(list(range(extent[axis * 2], extent[axis * 2 + 1] + gridSpacingVoxel[axis], gridSpacingVoxel[axis])))
        samplingPoints_shape = [len(gridAxesIJK[0]), len(gridAxesIJK[1]), len(gridAxesIJK[2]), 3]

        # create a grid transform with one vector at the corner of each slice
        # the transform is in the same space and orientation as the volume node
        import vtk
        gridImage = vtk.vtkImageData()
        gridImage.SetOrigin(*volumeNode.GetOrigin())
        gridImage.SetDimensions(samplingPoints_shape[:3])
        gridImage.SetSpacing(gridSpacingVoxel[0] * spacing[0], gridSpacingVoxel[1] * spacing[1], gridSpacingVoxel[2] * spacing[2])
        gridImage.AllocateScalars(vtk.VTK_DOUBLE, 3)
        transform = slicer.vtkOrientedGridTransform()
        directionMatrix = vtk.vtkMatrix4x4()
        volumeNode.GetIJKToRASDirectionMatrix(directionMatrix)
        transform.SetGridDirectionMatrix(directionMatrix)
        transform.SetDisplacementGridData(gridImage)

        # create the grid transform node
        gridTransform = slicer.vtkMRMLGridTransformNode()
        gridTransform.SetName(slicer.mrmlScene.GenerateUniqueName(volumeNode.GetName() + ' acquisition transform'))
        slicer.mrmlScene.AddNode(gridTransform)
        gridTransform.SetAndObserveTransformToParent(transform)

        # populate the grid so that each corner of each slice
        # is mapped from the source corner to the target corner

        nshape = tuple(reversed(gridImage.GetDimensions()))
        nshape = nshape + (3,)
        displacements = vtk.util.numpy_support.vtk_to_numpy(gridImage.GetPointData().GetScalars()).reshape(nshape)

        # Get displacements
        from math import sin, cos
        ijkToRas = vtk.vtkMatrix4x4()
        volumeNode.GetIJKToRASMatrix(ijkToRas)
        spacing = volumeNode.GetSpacing()
        center_IJK = [(extent[0] + extent[1]) / 2.0, extent[2], (extent[4] + extent[5]) / 2.0]
        sourcePoints_RAS = numpy.zeros(shape=samplingPoints_shape)
        targetPoints_RAS = numpy.zeros(shape=samplingPoints_shape)
        for k in range(samplingPoints_shape[2]):
            for j in range(samplingPoints_shape[1]):
                for i in range(samplingPoints_shape[0]):
                    samplingPoint_IJK = [gridAxesIJK[0][i], gridAxesIJK[1][j], gridAxesIJK[2][k], 1]
                    sourcePoint_RAS = np.array(ijkToRas.MultiplyPoint(samplingPoint_IJK)[:3])
                    radius = probeRadius - (samplingPoint_IJK[1] - center_IJK[1]) * spacing[1]
                    angleRad = (samplingPoint_IJK[0] - center_IJK[0]) * spacing[0] / probeRadius
                    targetPoint_RAS = np.array([
                        -radius * sin(angleRad),
                        radius * cos(angleRad) - probeRadius,
                        spacing[2] * (samplingPoint_IJK[2] - center_IJK[2])])
                    displacements[k][j][i] = targetPoint_RAS - sourcePoint_RAS

        return gridTransform