def setVectorVolume(self):
     vectorVolume = slicer.vtkMRMLGridTransformNode()
     slicer.mrmlScene.AddNode(vectorVolume)
     storageNode = vectorVolume.CreateDefaultStorageNode()
     slicer.mrmlScene.AddNode(storageNode)
     vectorVolume.SetAndObserveStorageNodeID(storageNode.GetID())
     self.vectorVolume = vectorVolume
Пример #2
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)
Пример #3
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
        from __main__ 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()))
        import vtk.util.numpy_support
        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
  def demonregister(self, fixedfile, movingfile):
    print 'Loading fixed from %s' % fixedfile
    print 'Loading moving from %s' % movingfile
    slicer.util.loadVolume(fixedfile) # Load fixed volume
    slicer.util.loadVolume(movingfile) # Load moving Volume
    fixedimgid = self._findimgid(fixedfile)[0]
    print 'Found Fixed Image ID: %s' % fixedimgid
    movingimgid = self._findimgid(movingfile)[0]
    print 'Found Moving Image ID: %s' % movingimgid
    fixedvol = slicer.util.getNode(pattern="*%s*" % fixedimgid)
    movingvol = slicer.util.getNode(pattern="*%s*" % movingimgid)
    print 'Found Nodes', fixedvol.GetID(), movingvol.GetID()

    # Create Output Volume if it does not exist
    outputvol = slicer.util.getNode('outputvol') 
    if outputvol is None:
      outputvol = slicer.vtkMRMLScalarVolumeNode()
      outputvol.SetName('outputvol')
      slicer.mrmlScene.AddNode(outputvol)
      assert slicer.util.getNode('outputvol') is not None 

    gridtransnode = slicer.vtkMRMLGridTransformNode()
    self.transname = '%s-%s' % (movingimgid[1:], fixedimgid[1:]) # Avoid from being taken as a volume
    gridtransnode.SetName(self.transname)
    slicer.mrmlScene.AddNode(gridtransnode)
    assert slicer.util.getNode(self.transname) is not None 

    # Set parameters    
    parameters = {}
    parameters['fixedVolume'] = fixedvol.GetID()
    parameters['movingVolume'] = movingvol.GetID()
    parameters['outputVolume'] = outputvol.GetID()
    parameters['outputDisplacementFieldVolume'] = gridtransnode.GetID()
    parameters['inputPixelType'] = 'float'
    parameters['outputPixelType'] = 'float'
    parameters['interpolationMode'] = 'WindowedSinc'
    parameters['registrationFilterType'] = 'Diffeomorphic'
    parameters['smoothDisplacementFieldSigma'] = '1'
    parameters['numberOfPyramidLevels'] = '5'
    parameters['numberOfPyramidLevels'] = '5'
    parameters['minimumFixedPyramid']   = '16,16,16'
    parameters['minimumMovingPyramid']  = '16,16,16'
    parameters['arrayOfPyramidLevelIterations'] = '300,50,30,20,15'
    parameters['numberOfHistogramBins'] = '256'
    parameters['numberOfMatchPoints'] = '10'
    parameters['medianFilterSize'] = '0,0,0'
    parameters['maskProcessingMode'] = 'NOMASK'
    parameters['lowerThresholdForBOBF'] = '0'
    parameters['upperThresholdForBOBF'] = '70'
    parameters['backgroundFillValue'] = '0'
    parameters['seedForBOBF'] = '0,0,0'
    parameters['neighborhoodForBOBF'] = '1,1,1'
    parameters['outputDisplacementFieldPrefix'] = 'none'
    parameters['checkerboardPatternSubdivisions'] = '4,4,4'
    parameters['gradient_type'] = '0'
    parameters['upFieldSmoothing'] = '0' 
    parameters['max_step_length'] = '2'
    parameters['numberOfBCHApproximationTerms'] = '2' 
    parameters['numberOfThreads'] = str(multiprocessing.cpu_count())
    parameters['histogramMatch'] = True

    # Run Demons Registration CLI
    demonscli = self.getCLINode(slicer.modules.brainsdemonwarp)
    self.addObserver(demonscli, self.StatusModifiedEvent, self.onFinishDemon)
    demonnode = slicer.cli.run(slicer.modules.brainsdemonwarp, demonscli, parameters, wait_for_completion=True)

    return True