Пример #1
0
    def test_ROI(self):
        """ Test the GetRASBounds & GetBounds method on a ROI.
    """
        #self.delayDisplay("Starting test_ROI")
        roiNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLAnnotationROINode())
        roiNode.SetXYZ(100, 300, -0.689)
        roiNode.SetRadiusXYZ(700, 8, 45)

        bounds = range(6)
        roiNode.GetRASBounds(bounds)
        untransformedBounds = [-600, 800, 292, 308, -45.689, 44.311]
        self.assertListAlmostEquals(bounds, untransformedBounds)

        roiNode.GetBounds(bounds)
        self.assertListAlmostEquals(bounds, untransformedBounds)

        transform = vtk.vtkTransform()
        transform.Translate([-5.0, +42.0, -0.1])
        transform.RotateWXYZ(41, 0.7, 0.6, 75)
        transform.Scale(2, 3, 10)
        transformNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLTransformNode())
        transformNode.ApplyTransform(transform)

        roiNode.SetAndObserveTransformNodeID(transformNode.GetID())
        transformedBounds = [
            -1520.2565880625004, 631.261028317266, -85.93765163061204,
            1790.9115952348277, -454.6252695921299, 454.0147697244433
        ]
        roiNode.GetRASBounds(bounds)
        self.assertListAlmostEquals(bounds, transformedBounds)

        roiNode.GetBounds(bounds)
        self.assertListAlmostEquals(bounds, untransformedBounds)
Пример #2
0
 def onImageChanged(self):
   if self.imageNode is not None:
     # Unparent
     self.imageNode.SetAndObserveTransformNodeID(None)
     self.imageNode = None
     self.imageNode = self.imageSelector.currentNode() 
     if self.imageNode is None: 
       print('Please select an US volume')
     if self.imageNode is not None: 
       self.imageNode.GetDisplayNode().SetAutoWindowLevel(0)
       self.imageNode.GetDisplayNode().SetWindowLevelMinMax(0,120)
       slicer.app.layoutManager().sliceWidget('Red').sliceLogic().GetSliceCompositeNode().SetBackgroundVolumeID(self.imageSelector.currentNode().GetID())
       # Configure volume reslice driver, transverse
       self.resliceLogic.SetDriverForSlice(self.imageSelector.currentNode().GetID(), slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed'))
       self.resliceLogic.SetModeForSlice(self.resliceLogic.MODE_TRANSVERSE, slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed'))
       slicer.app.layoutManager().sliceWidget("Red").sliceController().fitSliceToBackground()
       if biplaneButton.isChecked() == True: 
         self.ROInode = slicer.vtkMRMLAnnotationROINode()
         self.ROInode.setName("LeftROI")
         slicer.mrmlScene.addNode(self.ROInode)
   else:  
     self.imageNode = self.imageSelector.currentNode()
     self.imageNode.GetDisplayNode().SetAutoWindowLevel(0)
     self.imageNode.GetDisplayNode().SetWindowLevelMinMax(0,120)
     slicer.app.layoutManager().sliceWidget('Red').sliceLogic().GetSliceCompositeNode().SetBackgroundVolumeID(self.imageSelector.currentNode().GetID())
     # Configure volume reslice driver, transverse
     self.resliceLogic.SetDriverForSlice(self.imageSelector.currentNode().GetID(), slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed'))
     self.resliceLogic.SetModeForSlice(self.resliceLogic.MODE_TRANSVERSE, slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed'))
     slicer.app.layoutManager().sliceWidget("Red").sliceController().fitSliceToBackground()
Пример #3
0
  def test_ROI(self):
    """ Test the GetRASBounds & GetBounds method on a ROI.
    """
    #self.delayDisplay("Starting test_ROI")
    roiNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLAnnotationROINode())
    roiNode.SetXYZ(100, 300, -0.689)
    roiNode.SetRadiusXYZ(700, 8, 45)

    bounds = range(6)
    roiNode.GetRASBounds(bounds)
    untransformedBounds = [-600, 800, 292, 308, -45.689, 44.311]
    self.assertListAlmostEquals(bounds, untransformedBounds)

    roiNode.GetBounds(bounds)
    self.assertListAlmostEquals(bounds, untransformedBounds)

    transform = vtk.vtkTransform()
    transform.Translate([-5.0, +42.0, -0.1])
    transform.RotateWXYZ(41, 0.7, 0.6, 75)
    transform.Scale(2, 3, 10)
    transformNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLTransformNode())
    transformNode.ApplyTransform(transform)

    roiNode.SetAndObserveTransformNodeID(transformNode.GetID())
    transformedBounds = [-1520.2565880625004, 631.261028317266, -85.93765163061204, 1790.9115952348277, -454.6252695921299, 454.0147697244433]
    roiNode.GetRASBounds(bounds)
    self.assertListAlmostEquals(bounds, transformedBounds)

    roiNode.GetBounds(bounds)
    self.assertListAlmostEquals(bounds, untransformedBounds)
    def onRoiInitialization(self, scoutVolumeNodeName, roiNode):
        reconstructedNode = slicer.mrmlScene.GetNodesByName(
            scoutVolumeNodeName)
        reconstructedVolumeNode = slicer.vtkMRMLScalarVolumeNode.SafeDownCast(
            reconstructedNode.GetItemAsObject(0))

        roiCenterInit = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
        roiRadiusInit = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
        bounds = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

        #ROI is initialized to fit scout scan reconstructed volume
        if reconstructedVolumeNode:
            reconstructedVolumeNode.GetRASBounds(bounds)
            for i in range(0, 5, 2):
                roiCenterInit[i] = (bounds[i + 1] + bounds[i]) / 2
                roiRadiusInit[i] = (bounds[i + 1] - bounds[i]) / 2
            if roiNode:
                roiNode.SetXYZ(roiCenterInit[0], roiCenterInit[2],
                               roiCenterInit[4])
                roiNode.SetRadiusXYZ(roiRadiusInit[0], roiRadiusInit[2],
                                     roiRadiusInit[4])
            else:
                roiNode = slicer.vtkMRMLAnnotationROINode()
                roiNode.SetXYZ(roiCenterInit[0], roiCenterInit[2],
                               roiCenterInit[4])
                roiNode.SetRadiusXYZ(roiRadiusInit[0], roiRadiusInit[2],
                                     roiRadiusInit[4])
                roiNode.Initialize(slicer.mrmlScene)
                roiNode.SetDisplayVisibility(0)
                roiNode.SetInteractiveMode(1)
        return roiNode
    def test_3D_boundsUpdateROI(self):
        """ Test that the bounds update with an ROI.
    """
        logic = SlicerTransformInteractionTest1Logic()

        #self.delayDisplay("Starting test_3D_boundsUpdateROI")
        # Setup
        roiNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLAnnotationROINode())
        roiNode.SetXYZ(100, 300, -0.689)
        roiNode.SetRadiusXYZ(700, 8, 45)

        logic = SlicerTransformInteractionTest1Logic()
        tNode, tdNode = logic.addTransform()

        slicer.app.layoutManager(
        ).layout = slicer.vtkMRMLLayoutNode.SlicerLayoutOneUp3DView
        manager = logic.getModel3DDisplayableManager()
        self.assertIsNotNone(manager)

        widget = manager.GetWidget(tdNode)
        tdNode.SetEditorVisibility(True)
        self.assertTrue(widget.GetEnabled())

        representation = widget.GetRepresentation()
        transform = vtk.vtkTransform()

        expectedDefaultTransform = [
            [100.0, 0.0, 0.0, 0.0],
            [0.0, 100.0, 0.0, 0.0],
            [0.0, 0.0, 100.0, 0.0],
            [0.0, 0.0, 0.0, 1.0],
        ]
        representation.GetTransform(transform)
        self.assertTransform(transform, expectedDefaultTransform)

        tdNode.UpdateEditorBounds()
        representation.GetTransform(transform)
        self.assertTransform(transform, expectedDefaultTransform)

        roiNode.SetAndObserveTransformNodeID(tNode.GetID())
        representation.GetTransform(transform)
        self.assertTransform(transform, expectedDefaultTransform)

        tdNode.UpdateEditorBounds()
        roiDefaultTransform = [
            [2800.0, 0.0, 0.0, 100.0],
            [0.0, 32.0, 0.0, 300.0],
            [0.0, 0.0, 180.0, -0.689],
            [0.0, 0.0, 0.0, 1.0],
        ]
        representation.GetTransform(transform)
        self.assertTransform(transform, roiDefaultTransform)

        roiNode.SetAndObserveTransformNodeID(None)
        representation.GetTransform(transform)
        self.assertTransform(transform, roiDefaultTransform)

        tdNode.UpdateEditorBounds()
        representation.GetTransform(transform)
        self.assertTransform(transform, expectedDefaultTransform)
Пример #6
0
    def test_ModelCropper1(self):
        """ Ideally you should have several levels of tests.  At the lowest level
    tests should exercise the functionality of the logic with different inputs
    (both valid and invalid).  At higher levels your tests should emulate the
    way the user would interact with your code and confirm that it still works
    the way you intended.
    One of the most important features of the tests is that it should alert other
    developers when their changes will have an impact on the behavior of your
    module.  For example, if a developer removes a feature that you depend on,
    your test should break so they know that the feature is needed.
    """

        self.delayDisplay("Starting the test")
        sphereSource = vtk.vtkSphereSource()
        sphereSource.SetRadius(10)
        sphereSource.SetCenter(0, 0, 0)
        sphereSource.Update()
        modelsLogic = slicer.modules.models.logic()
        sphereNode = modelsLogic.AddModel(sphereSource.GetOutput())

        roiNode = slicer.vtkMRMLAnnotationROINode()
        slicer.mrmlScene.AddNode(roiNode)
        roiNode.SetXYZ(1, 1, 1)
        roiNode.SetRadiusXYZ(5, 5, 5)

        logic = ModelCropperLogic()
        logic.run(sphereNode, None, roiNode)

        self.delayDisplay('Test passed!')
  def onRoiInitialization(self, scoutVolumeNodeName, roiNode):
    reconstructedNode = slicer.mrmlScene.GetNodesByName(scoutVolumeNodeName)
    reconstructedVolumeNode = slicer.vtkMRMLScalarVolumeNode.SafeDownCast(reconstructedNode.GetItemAsObject(0))

    roiCenterInit = [0.0, 0.0, 0.0,
                     0.0, 0.0, 0.0]
    roiRadiusInit = [0.0, 0.0, 0.0,
                     0.0, 0.0, 0.0]
    bounds = [0.0, 0.0, 0.0,
              0.0, 0.0, 0.0]

    #ROI is initialized to fit scout scan reconstructed volume
    if reconstructedVolumeNode:
      reconstructedVolumeNode.GetRASBounds(bounds)
      for i in range(0,5,2):
        roiCenterInit[i] = (bounds[i+1] + bounds[i])/2
        roiRadiusInit[i] = (bounds[i+1] - bounds[i])/2
      if roiNode:
        roiNode.SetXYZ(roiCenterInit[0], roiCenterInit[2], roiCenterInit[4])
        roiNode.SetRadiusXYZ(roiRadiusInit[0], roiRadiusInit[2], roiRadiusInit[4])
      else:
        roiNode = slicer.vtkMRMLAnnotationROINode()
        roiNode.SetXYZ(roiCenterInit[0], roiCenterInit[2], roiCenterInit[4])
        roiNode.SetRadiusXYZ(roiRadiusInit[0], roiRadiusInit[2], roiRadiusInit[4])
        roiNode.Initialize(slicer.mrmlScene)
        roiNode.SetDisplayVisibility(0)
        roiNode.SetInteractiveMode(1)
    return roiNode
  def test_3D_boundsUpdateROI(self):
    """ Test that the bounds update with an ROI.
    """
    logic = SlicerTransformInteractionTest1Logic()

    #self.delayDisplay("Starting test_3D_boundsUpdateROI")
    # Setup
    roiNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLAnnotationROINode())
    roiNode.SetXYZ(100, 300, -0.689)
    roiNode.SetRadiusXYZ(700, 8, 45)

    logic = SlicerTransformInteractionTest1Logic()
    tNode, tdNode = logic.addTransform()

    slicer.app.layoutManager().layout = slicer.vtkMRMLLayoutNode.SlicerLayoutOneUp3DView
    manager = logic.getModel3DDisplayableManager()
    self.assertIsNotNone(manager)

    widget = manager.GetWidget(tdNode)
    tdNode.SetEditorVisibility(True)
    self.assertTrue(widget.GetEnabled())

    representation = widget.GetRepresentation()
    transform = vtk.vtkTransform()

    expectedDefaultTransform = [
      [100.0,   0.0,    0.0,    0.0],
      [0.0,   100.0,    0.0,    0.0],
      [0.0,     0.0,  100.0,    0.0],
      [0.0,     0.0,    0.0,    1.0],
      ]
    representation.GetTransform(transform)
    self.assertTransform(transform, expectedDefaultTransform)

    tdNode.UpdateEditorBounds()
    representation.GetTransform(transform)
    self.assertTransform(transform, expectedDefaultTransform)

    roiNode.SetAndObserveTransformNodeID(tNode.GetID())
    representation.GetTransform(transform)
    self.assertTransform(transform, expectedDefaultTransform)

    tdNode.UpdateEditorBounds()
    roiDefaultTransform = [
      [2800.0,  0.0,    0.0,   100.0],
      [0.0,     32.0,   0.0,   300.0],
      [0.0,     0.0,  180.0,    -0.689],
      [0.0,     0.0,    0.0,     1.0],
    ]
    representation.GetTransform(transform)
    self.assertTransform(transform, roiDefaultTransform)

    roiNode.SetAndObserveTransformNodeID(None)
    representation.GetTransform(transform)
    self.assertTransform(transform, roiDefaultTransform)

    tdNode.UpdateEditorBounds()
    representation.GetTransform(transform)
    self.assertTransform(transform, expectedDefaultTransform)
    def test_CropVolumeSelfTest(self):
        """
    Replicate the crashe in issue 3117
    """

        print("Running CropVolumeSelfTest Test case:")

        import SampleData

        vol = SampleData.downloadSample("MRHead")
        roi = slicer.vtkMRMLAnnotationROINode()
        roi.Initialize(slicer.mrmlScene)

        mainWindow = slicer.util.mainWindow()
        mainWindow.moduleSelector().selectModule('CropVolume')

        cropVolumeNode = slicer.vtkMRMLCropVolumeParametersNode()
        cropVolumeNode.SetScene(slicer.mrmlScene)
        cropVolumeNode.SetName('ChangeTracker_CropVolume_node')
        cropVolumeNode.SetIsotropicResampling(True)
        cropVolumeNode.SetSpacingScalingConst(0.5)
        slicer.mrmlScene.AddNode(cropVolumeNode)

        cropVolumeNode.SetInputVolumeNodeID(vol.GetID())
        cropVolumeNode.SetROINodeID(roi.GetID())

        cropVolumeLogic = slicer.modules.cropvolume.logic()
        cropVolumeLogic.Apply(cropVolumeNode)

        self.delayDisplay(
            'First test passed, closing the scene and running again')
        # test clearing the scene and running a second time
        slicer.mrmlScene.Clear(0)
        # the module will re-add the removed parameters node
        mainWindow.moduleSelector().selectModule('Transforms')
        mainWindow.moduleSelector().selectModule('CropVolume')
        cropVolumeNode = slicer.mrmlScene.GetNodeByID(
            'vtkMRMLCropVolumeParametersNode1')
        vol = SampleData.downloadSample("MRHead")
        roi = slicer.vtkMRMLAnnotationROINode()
        roi.Initialize(slicer.mrmlScene)
        cropVolumeNode.SetInputVolumeNodeID(vol.GetID())
        cropVolumeNode.SetROINodeID(roi.GetID())
        cropVolumeLogic.Apply(cropVolumeNode)

        self.delayDisplay('Test passed')
Пример #10
0
  def test_CropVolumeSelfTest(self):
    """
    Replicate the crashe in issue 3117
    """

    print("Running CropVolumeSelfTest Test case:")

    import SampleData

    vol = SampleData.downloadSample("MRHead")
    roi = slicer.vtkMRMLAnnotationROINode()
    roi.Initialize(slicer.mrmlScene)

    mainWindow = slicer.util.mainWindow()
    mainWindow.moduleSelector().selectModule('CropVolume')

    cropVolumeNode = slicer.vtkMRMLCropVolumeParametersNode()
    cropVolumeNode.SetScene(slicer.mrmlScene)
    cropVolumeNode.SetName('ChangeTracker_CropVolume_node')
    cropVolumeNode.SetIsotropicResampling(True)
    cropVolumeNode.SetSpacingScalingConst(0.5)
    slicer.mrmlScene.AddNode(cropVolumeNode)

    cropVolumeNode.SetInputVolumeNodeID(vol.GetID())
    cropVolumeNode.SetROINodeID(roi.GetID())

    cropVolumeLogic = slicer.modules.cropvolume.logic()
    cropVolumeLogic.Apply(cropVolumeNode)

    self.delayDisplay('First test passed, closing the scene and running again')
    # test clearing the scene and running a second time
    slicer.mrmlScene.Clear(0)
    # the module will re-add the removed parameters node
    mainWindow.moduleSelector().selectModule('Transforms')
    mainWindow.moduleSelector().selectModule('CropVolume')
    cropVolumeNode = slicer.mrmlScene.GetNodeByID('vtkMRMLCropVolumeParametersNode1')
    vol = SampleData.downloadSample("MRHead")
    roi = slicer.vtkMRMLAnnotationROINode()
    roi.Initialize(slicer.mrmlScene)
    cropVolumeNode.SetInputVolumeNodeID(vol.GetID())
    cropVolumeNode.SetROINodeID(roi.GetID())
    cropVolumeLogic.Apply(cropVolumeNode)

    self.delayDisplay('Test passed')
    def test_ZFrameRegistrationWithROI1(self):
        """ Ideally you should have several levels of tests.  At the lowest level
    tests should exercise the functionality of the logic with different inputs
    (both valid and invalid).  At higher levels your tests should emulate the
    way the user would interact with your code and confirm that it still works
    the way you intended.
    One of the most important features of the tests is that it should alert other
    developers when their changes will have an impact on the behavior of your
    module.  For example, if a developer removes a feature that you depend on,
    your test should break so they know that the feature is needed.
    """

        self.delayDisplay("Starting the test")
        #
        # first, get some data
        #

        currentFilePath = os.path.dirname(os.path.realpath(__file__))
        imageDataPath = os.path.join(
            os.path.abspath(os.path.join(currentFilePath, os.pardir)),
            "ZFrameRegistration", "Data", "Input", "CoverTemplateMasked.nrrd")
        _, imageDataNode = slicer.util.loadVolume(imageDataPath,
                                                  returnNode=True)
        slicer.app.processEvents()
        self.delayDisplay('Finished with loading')

        zFrameRegistrationLogic = ZFrameRegistrationWithROILogic()
        ROINode = slicer.vtkMRMLAnnotationROINode()
        ROINode.SetName("ROINodeForCropping")
        ROICenterPoint = [
            -6.91920280456543, 15.245062828063965, -101.13504791259766
        ]
        ROINode.SetXYZ(ROICenterPoint)
        ROIRadiusXYZ = [
            36.46055603027344, 38.763328552246094, 36.076759338378906
        ]
        ROINode.SetRadiusXYZ(ROIRadiusXYZ)
        slicer.mrmlScene.AddNode(ROINode)
        slicer.app.processEvents()

        zFrameRegistrationLogic.runZFrameOpenSourceRegistration(
            imageDataNode, coverTemplateROI=ROINode)
        slicer.app.processEvents()
        transformNode = zFrameRegistrationLogic.openSourceRegistration.outputTransform
        transformMatrix = transformNode.GetTransformFromParent().GetMatrix()
        testResultMatrix = [0.0] * 16
        transformMatrix.DeepCopy(testResultMatrix, transformMatrix)
        for index in range(len(self.groundTruthMatrix)):
            self.assertEqual(
                self.isclose(float(testResultMatrix[index]),
                             float(self.groundTruthMatrix[index])), True)
        zFrameRegistrationLogic.clearVolumeNodes()

        self.delayDisplay('Test passed!')
    def runDefineCropROIVoxel(self, inputVol):

        #create crop volume parameter node
        cropParamNode = slicer.vtkMRMLCropVolumeParametersNode()
        cropParamNode.SetScene(slicer.mrmlScene)
        cropParamNode.SetName('Template_ROI')
        cropParamNode.SetInputVolumeNodeID(inputVol.GetID())

        #create ROI
        template_roi = slicer.vtkMRMLAnnotationROINode()
        slicer.mrmlScene.AddNode(template_roi)
        cropParamNode.SetROINodeID(template_roi.GetID())

        #Fit roi to input image
        slicer.mrmlScene.AddNode(cropParamNode)
        slicer.modules.cropvolume.logic().SnapROIToVoxelGrid(cropParamNode)
        slicer.modules.cropvolume.logic().FitROIToInputVolume(cropParamNode)

        return template_roi
Пример #13
0
    def createROI(self):
        # Verificar se ha apenas um fiducial
        fiducialNode = self.fiducialSelector.currentNode()
        numFiducials = fiducialNode.GetNumberOfFiducials()
        if numFiducials > 1:
            slicer.util.messageBox(
                "Nao ha' fiducial definido para criar a ROI.")
            return
        if numFiducials > 1:
            slicer.util.messageBox(
                "Encontrado mais de 1 fiducial.\nSo' pode haver um.")
            return

        # Localizando o Fiducial e criando a ROI
        L = 50.0
        P = 35.0
        A = 12.5

        ras = [0.0, 0.0, 0.0]
        pos = [0.0, 0.0, 0.0]
        fiducialNode.GetNthFiducialPosition(0, ras)

        pos[0] = ras[0] - 10
        pos[1] = ras[1] - 25
        pos[2] = ras[2] + 7.5

        min = 0
        max = 0
        minvalue = 0

        ROI = slicer.vtkMRMLAnnotationROINode()
        ROI.SetName('RoiNode')
        slicer.mrmlScene.AddNode(ROI)
        ROI.SetXYZ(pos)
        ROI.SetRadiusXYZ(L, P, A)
        ROI.SetDisplayVisibility(True)

        self.setROIButton.enabled = False

        slicer.app.processEvents()  #atualiza tela

        return ROI
Пример #14
0
  def defineROIRun(self, originalVolume, cropVolumeParameterNode):
    roi = slicer.vtkMRMLAnnotationROINode()
    roi.SetName(originalVolume.GetName()+ "_ROI")
    slicer.mrmlScene.AddNode(roi)

    croppedVolume = slicer.vtkMRMLScalarVolumeNode()
    croppedVolume.SetName(originalVolume.GetName() + "_Cropped")
    slicer.mrmlScene.AddNode(croppedVolume)

    cropVolumeParameterNode.SetInputVolumeNodeID(originalVolume.GetID())
    cropVolumeParameterNode.SetOutputVolumeNodeID(croppedVolume.GetID())
    cropVolumeParameterNode.SetROINodeID(roi.GetID())

    # set ROI Annotation box to cover the whole volume
    volumeBounds_ROI, roiCenter, roiRadius = [0, 0, 0, 0, 0, 0], [0, 0, 0], [0, 0, 0]
    originalVolume.GetSliceBounds(volumeBounds_ROI, vtk.vtkMatrix4x4())
    for i in range(3):
      roiCenter[i] = (volumeBounds_ROI[i * 2 + 1] + volumeBounds_ROI[i * 2]) / 2
      roiRadius[i] = (volumeBounds_ROI[i * 2 + 1] - volumeBounds_ROI[i * 2]) / 2
    roi.SetXYZ(roiCenter)
    roi.SetRadiusXYZ(roiRadius)
  def test_PETLiverUptakeMeasurementQR2(self):
    """ test segmentation options
    """
    try:
      self.assertIsNotNone( slicer.modules.petliveruptakemeasurement )
      with DICOMUtils.TemporaryDICOMDatabase(self.tempDicomDatabaseDir) as db:
        self.assertTrue(db.isOpen)
        self.assertEqual(slicer.dicomDatabase, db)
        self.delayDisplay('Loading PET DICOM dataset (including download if necessary)')
        petNode = self.loadTestData()

        qrWidget = slicer.modules.PETLiverUptakeMeasurementQRWidget
        qrWidget.inputSelector.setCurrentNode(petNode)
        segmentationNode = qrWidget.segmentationSelector.addNode()

        self.delayDisplay('Running segmentation with standard settings')
        qrWidget.segmentButton.click()
        self.assertTrue(abs(float(qrWidget.meanValueLineEdit.text)-2.36253)<0.01)

        self.delayDisplay('Specifying annotation ROI')
        roi=slicer.vtkMRMLAnnotationROINode()
        roi.SetXYZ([-34,243,-1168])
        roi.SetRadiusXYZ([85,102,82])
        roi.SetName('ROI')
        slicer.mrmlScene.AddNode(roi)
        qrWidget.regionSelector.setCurrentNode(roi)
        qrWidget.segmentButton.click()
        self.assertTrue(abs(float(qrWidget.meanValueLineEdit.text)-2.91891)<0.01)

        self.delayDisplay('Changing erosion range')
        originalErosion = qrWidget.erosionSlider.value
        qrWidget.erosionSlider.value = 0
        qrWidget.segmentButton.click()
        self.assertTrue(abs(float(qrWidget.meanValueLineEdit.text)-2.71982)<0.01)

        self.delayDisplay('Changing thresholds')
        originalMinimValue = qrWidget.thresholdRangeSlider.minimumValue
        originalMaximumValue = qrWidget.thresholdRangeSlider.maximumValue
        qrWidget.thresholdRangeSlider.minimumValue = 2
        qrWidget.thresholdRangeSlider.maximumValue = 20
        qrWidget.segmentButton.click()
        self.assertTrue(abs(float(qrWidget.meanValueLineEdit.text)-3.72669)<0.01)

        self.delayDisplay('Completing and writing DICOM report')
        qrWidget.readerValueLineEdit.text = 'semiautotest'
        self.assertTrue(qrWidget.saveReport(completed=True))

        self.delayDisplay('Testing that report was saved as semiautomatic result')
        import dicom
        patientUID = DICOMUtils.getDatabasePatientUIDByPatientName('QIN-HEADNECK-01-0139')
        studies = slicer.dicomDatabase.studiesForPatient(patientUID)
        series = slicer.dicomDatabase.seriesForStudy(studies[0])
        SEGSeries = None
        for serie in series:
          description = slicer.dicomDatabase.descriptionForSeries(serie)
          if description=='Semiautomatic Liver Reference Region Segmentation':
            SEGSeries = serie
        self.assertIsNotNone(SEGSeries)

        # reset values
        qrWidget.regionSelector.removeCurrentNode()
        qrWidget.erosionSlider.value = originalErosion
        qrWidget.thresholdRangeSlider.minimumValue = originalMinimValue
        qrWidget.thresholdRangeSlider.maximumValue = originalMaximumValue

        # clean up data from DICOM database
        db.removePatient(patientUID)

        self.delayDisplay('Test passed!')

    except Exception, e:
      import traceback
      traceback.print_exc()
      self.delayDisplay('Test caused exception!\n' + str(e),self.delayMs*2)
  def test_ThresholdThreading(self):
    """
    Replicate the issue reported in bug 1822 where splitting
    a grow-cut produced volume causes a multi-threading related
    issue on mac release builds
    """
    self.delayDisplay("Starting the test")

    #
    # first, get some sample data
    #
    self.delayDisplay("Get some data")
    import SampleData
    head = SampleData.downloadSample("MRHead")

    #
    # now, define an ROI in it
    #
    roi = slicer.vtkMRMLAnnotationROINode()
    slicer.mrmlScene.AddNode(roi)
    roi.SetXYZ(-2, 104, -80)
    roi.SetRadiusXYZ(30, 30, 30)

    #
    # apply the cropping to the head
    #
    cropLogic = slicer.modules.cropvolume.logic()
    cvpn = slicer.vtkMRMLCropVolumeParametersNode()
    cvpn.SetROINodeID( roi.GetID() )
    cvpn.SetInputVolumeNodeID( head.GetID() )
    cropLogic.Apply( cvpn )
    croppedHead = slicer.mrmlScene.GetNodeByID( cvpn.GetOutputVolumeNodeID() )

    #
    # create a label map and set it for editing
    #
    volumesLogic = slicer.modules.volumes.logic()
    croppedHeadLabel = volumesLogic.CreateAndAddLabelVolume( slicer.mrmlScene, croppedHead, croppedHead.GetName() + '-label' )
    selectionNode = slicer.app.applicationLogic().GetSelectionNode()
    selectionNode.SetActiveVolumeID( croppedHead.GetID() )
    selectionNode.SetActiveLabelVolumeID( croppedHeadLabel.GetID() )
    slicer.app.applicationLogic().PropagateVolumeSelection(0)


    #
    # got to the editor and do some drawing
    #
    self.delayDisplay("Paint some things")
    parameterNode = EditUtil.getParameterNode()
    lm = slicer.app.layoutManager()
    paintEffect = EditorLib.PaintEffectOptions()
    paintEffect.setMRMLDefaults()
    paintEffect.__del__()
    sliceWidget = lm.sliceWidget('Red')
    paintTool = EditorLib.PaintEffectTool(sliceWidget)
    EditUtil.setLabel(1)
    paintTool.paintAddPoint(100,100)
    paintTool.paintApply()
    EditUtil.setLabel(2)
    paintTool.paintAddPoint(200,200)
    paintTool.paintApply()
    paintTool.cleanup()
    paintTool = None

    self.delayDisplay("Now grow cut")

    #
    # now do GrowCut
    #
    growCutLogic = EditorLib.GrowCutEffectLogic(sliceWidget.sliceLogic())
    growCutLogic.growCut()

    #
    # now split the volume, merge it back, and see if it looks right
    #
    preArray = slicer.util.array(croppedHeadLabel.GetName())
    slicer.util.selectModule('Editor')
    slicer.util.findChildren(text='Split Merge Volume')[0].clicked()
    slicer.util.findChildren(text='Merge All')[0].clicked()
    postArray = slicer.util.array(croppedHeadLabel.GetName())

    if (postArray - preArray).max() != 0:
      print("!$!$!#!@#!@!@$%! Test Failed!!")
    else:
      print("Ahh... test passed.")

    self.assertEqual((postArray - preArray).max(), 0)

    self.delayDisplay("Test passed!")
    def refineLandmark(self, state):
        """Refine the specified landmark"""
        # Refine landmark, or if none, do nothing
        #     Crop images around the fiducial
        #     Affine registration of the cropped images
        #     Transform the fiducial using the transformation
        #
        # No need to take into account the current transformation because landmarks are in World RAS
        timing = False
        if self.VerboseMode == "Verbose":
            timing = True

        if state.logic.cropLogic is None:
            print(
                "Cannot refine landmarks. CropVolume module is not available.")

        if state.fixed == None or state.moving == None or state.fixedFiducials == None or state.movingFiducials == None or state.currentLandmarkName == None:
            print "Cannot refine landmarks. Images or landmarks not selected."
            return

        print("Refining landmark " +
              state.currentLandmarkName) + " using " + self.name

        start = time.time()

        volumes = (state.fixed, state.moving)
        (fixedVolume, movingVolume) = volumes

        slicer.mrmlScene.StartState(slicer.mrmlScene.BatchProcessState)
        landmarks = state.logic.landmarksForVolumes(volumes)

        cvpn = slicer.vtkMRMLCropVolumeParametersNode()
        cvpn.SetInterpolationMode(1)
        cvpn.SetVoxelBased(1)
        fixedPoint = [
            0,
        ] * 3
        movingPoint = [
            0,
        ] * 3

        (fixedFiducial, movingFiducial) = landmarks[state.currentLandmarkName]

        (fixedList, fixedIndex) = fixedFiducial
        (movingList, movingIndex) = movingFiducial

        # define an roi for the fixed
        if timing: roiStart = time.time()
        roiFixed = slicer.vtkMRMLAnnotationROINode()
        slicer.mrmlScene.AddNode(roiFixed)

        fixedList.GetNthFiducialPosition(fixedIndex, fixedPoint)
        roiFixed.SetDisplayVisibility(0)
        roiFixed.SelectableOff()
        roiFixed.SetXYZ(fixedPoint)
        roiFixed.SetRadiusXYZ(30, 30, 30)

        # crop the fixed. note we hide the display node temporarily to avoid the automated
        # window level calculation on temporary nodes created by cloning
        cvpn.SetROINodeID(roiFixed.GetID())
        cvpn.SetInputVolumeNodeID(fixedVolume.GetID())
        fixedDisplayNode = fixedVolume.GetDisplayNode()
        fixedVolume.SetAndObserveDisplayNodeID(
            'This is not a valid DisplayNode ID')
        if timing: roiEnd = time.time()
        if timing: cropStart = time.time()
        state.logic.cropLogic.Apply(cvpn)
        if timing: cropEnd = time.time()
        croppedFixedVolume = slicer.mrmlScene.GetNodeByID(
            cvpn.GetOutputVolumeNodeID())
        fixedVolume.SetAndObserveDisplayNodeID(fixedDisplayNode.GetID())

        # define an roi for the moving
        if timing: roi2Start = time.time()
        roiMoving = slicer.vtkMRMLAnnotationROINode()
        slicer.mrmlScene.AddNode(roiMoving)

        movingList.GetNthFiducialPosition(movingIndex, movingPoint)
        roiMoving.SetDisplayVisibility(0)
        roiMoving.SelectableOff()
        roiMoving.SetXYZ(movingPoint)
        if self.LocalBRAINSFitMode == "Small":
            roiMoving.SetRadiusXYZ(45, 45, 45)
        else:
            roiMoving.SetRadiusXYZ(60, 60, 60)

        # crop the moving. note we hide the display node temporarily to avoid the automated
        # window level calculation on temporary nodes created by cloning
        cvpn.SetROINodeID(roiMoving.GetID())
        cvpn.SetInputVolumeNodeID(movingVolume.GetID())
        movingDisplayNode = movingVolume.GetDisplayNode()
        movingVolume.SetAndObserveDisplayNodeID(
            'This is not a valid DisplayNode ID')
        if timing: roi2End = time.time()
        if timing: crop2Start = time.time()
        state.logic.cropLogic.Apply(cvpn)
        if timing: crop2End = time.time()
        croppedMovingVolume = slicer.mrmlScene.GetNodeByID(
            cvpn.GetOutputVolumeNodeID())
        movingVolume.SetAndObserveDisplayNodeID(movingDisplayNode.GetID())

        if timing:
            print 'Time to set up fixed ROI was ' + str(roiEnd -
                                                        roiStart) + ' seconds'
        if timing:
            print 'Time to set up moving ROI was ' + str(
                roi2End - roi2Start) + ' seconds'
        if timing:
            print 'Time to crop fixed volume ' + str(cropEnd -
                                                     cropStart) + ' seconds'
        if timing:
            print 'Time to crop moving volume ' + str(crop2End -
                                                      crop2Start) + ' seconds'

        #
        transform = slicer.vtkMRMLLinearTransformNode()
        slicer.mrmlScene.AddNode(transform)
        matrix = vtk.vtkMatrix4x4()

        # define the registration parameters
        minPixelSpacing = min(croppedFixedVolume.GetSpacing())
        parameters = {}
        parameters['fixedVolume'] = croppedFixedVolume.GetID()
        parameters['movingVolume'] = croppedMovingVolume.GetID()
        parameters['linearTransform'] = transform.GetID()
        parameters['useRigid'] = True
        parameters['initializeTransformMode'] = 'useGeometryAlign'
        parameters['samplingPercentage'] = 0.2
        parameters['minimumStepLength'] = 0.1 * minPixelSpacing
        parameters['maximumStepLength'] = minPixelSpacing

        # run the registration
        if timing: regStart = time.time()
        slicer.cli.run(slicer.modules.brainsfit,
                       None,
                       parameters,
                       wait_for_completion=True)
        if timing: regEnd = time.time()
        if timing:
            print 'Time for local registration ' + str(regEnd -
                                                       regStart) + ' seconds'

        # apply the local transform to the landmark
        #print transform
        if timing: resultStart = time.time()
        transform.GetMatrixTransformToWorld(matrix)
        matrix.Invert()
        tp = [
            0,
        ] * 4
        tp = matrix.MultiplyPoint(fixedPoint + [
            1,
        ])
        #print fixedPoint, movingPoint, tp[:3]

        movingList.SetNthFiducialPosition(movingIndex, tp[0], tp[1], tp[2])
        if timing: resultEnd = time.time()
        if timing:
            print 'Time for transforming landmark was ' + str(
                resultEnd - resultStart) + ' seconds'

        # clean up cropped volmes, need to reset the foreground/background display before we delete it
        if timing: cleanUpStart = time.time()
        slicer.mrmlScene.RemoveNode(croppedFixedVolume)
        slicer.mrmlScene.RemoveNode(croppedMovingVolume)
        slicer.mrmlScene.RemoveNode(roiFixed)
        slicer.mrmlScene.RemoveNode(roiMoving)
        slicer.mrmlScene.RemoveNode(transform)
        roiFixed = None
        roiMoving = None
        transform = None
        matrix = None
        if timing: cleanUpEnd = time.time()
        if timing:
            print 'Cleanup took ' + str(cleanUpEnd - cleanUpStart) + ' seconds'

        end = time.time()
        print 'Refined landmark ' + state.currentLandmarkName + ' in ' + str(
            end - start) + ' seconds'

        slicer.mrmlScene.EndState(slicer.mrmlScene.BatchProcessState)
Пример #18
0
    def run(self, inputVolume, labelMap, ROIValue, cortValue):
        logging.info('Processing started')

        if not self.isValidInputOutputData(inputVolume, labelMap):
            slicer.util.errorDisplay('Volumes de entrada e saida sao so mesmos. Escolha outros volumes')
            return False

        volumeLogic = slicer.modules.volumes.logic()
        slicer.app.processEvents()

        # Executar correcao N4ITK
        self.progressBar.value = 10
        slicer.app.processEvents()
        n4itkVolume = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode", inputVolume.GetName() + ' N4ITK')
        parameters = {}
        parameters["inputImageName"] = inputVolume.GetID()
        parameters["outputImageName"] = n4itkVolume.GetID()
        n4itkModule = slicer.modules.n4itkbiasfieldcorrection
        slicer.cli.run(n4itkModule, None, parameters, wait_for_completion=True)
        logging.info('N4ITK finished')

        # Executar CastScalarVolume
        self.progressBar.value = 20
        slicer.app.processEvents()
        castVolume = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode", inputVolume.GetName() + ' Cast Volume')
        parameters.clear()
        parameters["InputVolume"] = n4itkVolume.GetID()
        parameters["OutputVolume"] = castVolume.GetID()
        parameters["Type"] = "Int"
        csv = slicer.modules.castscalarvolume
        slicer.cli.run(csv, None, parameters, wait_for_completion=True)
        logging.info('Cast Scalar Volume finished')

        # Inverter voxels do Volume
        self.progressBar.value = 30
        slicer.app.processEvents()
        invertVolume = volumeLogic.CloneVolume(slicer.mrmlScene, castVolume, inputVolume.GetName() + ' Inverted Volume')
        invertVolume.SetName(inputVolume.GetName() + ' Inverted Volume')
        a = slicer.util.array(invertVolume.GetName())
        Max=0
        if (a.max() < 256):                              # 8 bits
            Max=255
        if (a.max() >= 256) and (a.max() < 4096):        # 12 bits
            Max=4095
        if (a.max() >= 4096) and (a.max() < 16384):      # 14 bits
                Max=16383
        if (a.max() >= 16384) and (a.max() < 65536):     # 16 bits
            Max=65535

        a[:] = Max -a                                    #inverte os valores dos voxels
        logging.info('Inverted Volume finished')
        #invertVolume.GetImageData().Modified()

        # Calcular osso cortical
        self.progressBar.value = 40
        slicer.app.processEvents()
        volumeArray = slicer.util.array(invertVolume.GetName())
        labelArray = slicer.util.array(labelMap.GetName())
        points = numpy.where(labelArray == cortValue)
        values = volumeArray[points]
        ICort = values.mean()
        logging.info('Calculo do Osso Cortical (ICort) finished')

        # Calculo da media da ROI (ITrab)
        self.progressBar.value = 50
        slicer.app.processEvents()
        ROIArray = slicer.util.array(invertVolume.GetName())
        labelArray = slicer.util.array(labelMap.GetName())
        points = numpy.where(labelArray == ROIValue)
        values = volumeArray[points]
        ocorrencias = numpy.bincount(values)                   #contar ocorrencias. Posicao e o valor!
        ocorrenciasList = list(ocorrencias)                    #converter array numpy em lista
        ocurrenciasListSorted = numpy.sort(ocorrenciasList)    #ordenar array
        ITrab = values.mean()                                  #media dos pontos
        logging.info('Calculo da ROI (ITrab) finished')

        # capturar o valor do pixel (posicao) no vetor do pico do histograma
        picoPixelValue=ocorrenciasList.index(ocorrencias.max())

        # Encontrar ILow
        if (ocorrencias.max()/2) in ocorrencias:
            ILow=ocorrenciasList.index(ocorrencias.max()/2)
        else:
            for x in ocurrenciasListSorted:
                if x > (ocorrencias.max()/2):
                    posterior=ocorrenciasList.index(x)
                    break
                else:
                    anterior=ocorrenciasList.index(x)
        try:
            ILow
            #print 'ilow existe'
        except NameError:
            #print 'ilow nao existe'
            if (posterior-(ocorrencias.max()/2)) <= ((ocorrencias.max()/2)-anterior):
                ILow = posterior
            else:
                ILow = anterior

        logging.info('Procura ILow finished')

        FVTO = (ITrab - ILow) / (ICort - ILow)
        logging.info('Calculo do FVTO finished')

        # Executa Mask Scalar Volume no ROI
        self.progressBar.value = 60
        slicer.app.processEvents()
        ROIVolume = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode", inputVolume.GetName() + ' ROI Volume')
        parameters.clear()
        parameters["InputVolume"] = invertVolume.GetID()
        parameters["MaskVolume"] = labelMap.GetID()
        parameters["OutputVolume"] = ROIVolume.GetID()
        parameters["Label"] = ROIValue
        maskScalarVolume = slicer.modules.maskscalarvolume
        slicer.cli.run(maskScalarVolume, None, parameters, wait_for_completion=True)
        logging.info('Mask Scalar Volume finished')

        # Posicionando a ROI para cortar a imagem
        self.progressBar.value = 70
        slicer.app.processEvents()

        # Achar o centro da imagem segmentada
        array = slicer.util.array(ROIVolume.GetName())
        points = numpy.where(array > 0)

        # Calculo da posicao
        pos = [0.0, 0.0, 0.0]
        IJKtoRASMatrix = vtk.vtkMatrix4x4()
        ROIVolume.GetIJKToRASMatrix(IJKtoRASMatrix)
        i = points[2].max() - (points[2].max() - points[2].min())/2
        j = points[1].max() - (points[1].max() - points[1].min())/2
        k = points[0].max() - (points[0].max() - points[0].min())/2
        IJK = [i, j, k, 1]
        RAS = IJKtoRASMatrix.MultiplyPoint(IJK)
        pos[0] = RAS[0]
        pos[1] = RAS[1]
        pos[2] = RAS[2]

        # Calculo das dimensoes
        spacing = [0.0, 0.0, 0.0]
        spacing = ROIVolume.GetSpacing()
        L = ((points[0].max() - points[0].min())/2*spacing[0])+spacing[0]
        P = ((points[2].max() - points[2].min())/2*spacing[2])+spacing[1]
        A = ((points[1].max() - points[1].min())/2*spacing[1])+spacing[1]
        print L, P, A

        # Criar a ROI
        ROI = slicer.vtkMRMLAnnotationROINode()
        ROI.SetName(inputVolume.GetName() + ' ROI')
        slicer.mrmlScene.AddNode(ROI)
        ROI.SetXYZ(pos)
        ROI.SetRadiusXYZ(L, P, A)
        ROI.SetDisplayVisibility(True)

        # Realiza o Crop da imagem
        #Crop Voxel Based
        self.progressBar.value = 80
        slicer.app.processEvents()
        cropLogic = slicer.modules.cropvolume.logic()
        cropVolume = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScalarVolumeNode", inputVolume.GetName() + ' Cropped Volume')
        parametersNode = slicer.vtkMRMLCropVolumeParametersNode()
        parametersNode.SetInputVolumeNodeID(ROIVolume.GetID())
        parametersNode.SetOutputVolumeNodeID(cropVolume.GetID())
        parametersNode.SetROINodeID(ROI.GetID())
        parametersNode.SetVoxelBased(True)
        slicer.mrmlScene.AddNode(parametersNode)
        cropLogic.SnapROIToVoxelGrid(parametersNode)
        cropLogic.Apply(parametersNode)

        # Binarizar volume
        self.progressBar.value = 90
        slicer.app.processEvents()
        resultVolume = volumeLogic.CloneVolume(slicer.mrmlScene, cropVolume, inputVolume.GetName() + ' Result Volume')
        resultVolume.SetName(inputVolume.GetName() + ' Result Volume')
        arrayResult = slicer.util.array(resultVolume.GetName())
        arrayResult[arrayResult < ITrab] = 0
        arrayResult[arrayResult >= ITrab] = Max
        logging.info('Volume ROI Binario finished')

        # Popular tabela
        logging.info('Popular tabela')
        rowIndex = self.table.AddEmptyRow()
        self.table.SetCellText(rowIndex, 0, inputVolume.GetName())
        self.table.SetCellText(rowIndex, 1, str(ICort))
        self.table.SetCellText(rowIndex, 2, str(ITrab))
        self.table.SetCellText(rowIndex, 3, str(ILow))
        self.table.SetCellText(rowIndex, 4, str(FVTO))

        # Exibir o resultado
        logging.info('Exibir resultado')
        for color in ['Red', 'Yellow', 'Green']:
            slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetBackgroundVolumeID(resultVolume.GetID())

        self.resultButton.enabled = True
        self.progressBar.value = 100
        slicer.app.processEvents()

        logging.info('Processing finished')

        return True
Пример #19
0
  def TestSection_2_qMRMLSegmentationGeometryWidget(self):
    logging.info('Test section 2: qMRMLSegmentationGeometryWidget')

    import vtkSegmentationCore
    binaryLabelmapReprName = vtkSegmentationCore.vtkSegmentationConverter.GetBinaryLabelmapRepresentationName()
    closedSurfaceReprName = vtkSegmentationCore.vtkSegmentationConverter.GetClosedSurfaceRepresentationName()

    # Use MRHead and Tinypatient for testing
    import SampleData
    sampleDataLogic = SampleData.SampleDataLogic()
    mrVolumeNode = sampleDataLogic.downloadMRHead()
    [tinyVolumeNode, tinySegmentationNode] = sampleDataLogic.downloadSample('TinyPatient')

    # Convert MRHead to oriented image data
    import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic
    mrOrientedImageData = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.CreateOrientedImageDataFromVolumeNode(mrVolumeNode)
    mrOrientedImageData.UnRegister(None)

    # Create segmentation node with binary labelmap master and one segment with MRHead geometry
    segmentationNode = slicer.vtkMRMLSegmentationNode()
    segmentationNode.GetSegmentation().SetMasterRepresentationName(binaryLabelmapReprName)
    geometryStr = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(mrOrientedImageData)
    segmentationNode.GetSegmentation().SetConversionParameter(
      vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), geometryStr)
    slicer.mrmlScene.AddNode(segmentationNode)
    threshold = vtk.vtkImageThreshold()
    threshold.SetInputData(mrOrientedImageData)
    threshold.ThresholdByUpper(16.0)
    threshold.SetInValue(1)
    threshold.SetOutValue(0)
    threshold.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR)
    threshold.Update()
    segmentOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()
    segmentOrientedImageData.DeepCopy(threshold.GetOutput())
    mrImageToWorldMatrix = vtk.vtkMatrix4x4()
    mrOrientedImageData.GetImageToWorldMatrix(mrImageToWorldMatrix)
    segmentOrientedImageData.SetImageToWorldMatrix(mrImageToWorldMatrix)
    segment = vtkSegmentationCore.vtkSegment()
    segment.SetName('Brain')
    segment.SetColor(0.0,0.0,1.0)
    segment.AddRepresentation(binaryLabelmapReprName, segmentOrientedImageData)
    segmentationNode.GetSegmentation().AddSegment(segment)

    # Create geometry widget
    geometryWidget = slicer.qMRMLSegmentationGeometryWidget()
    geometryWidget.setSegmentationNode(segmentationNode)
    geometryWidget.editEnabled = True
    geometryImageData = vtkSegmentationCore.vtkOrientedImageData() # To contain the output later

    # Volume source with no transforms
    geometryWidget.setSourceNode(tinyVolumeNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (49,49,23), (248.8439, 248.2890, -123.75),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

    # Transformed volume source
    translationTransformMatrix = vtk.vtkMatrix4x4()
    translationTransformMatrix.SetElement(0,3,24.5)
    translationTransformMatrix.SetElement(1,3,24.5)
    translationTransformMatrix.SetElement(2,3,11.5)
    translationTransformNode = slicer.vtkMRMLLinearTransformNode()
    translationTransformNode.SetName('TestTranslation')
    slicer.mrmlScene.AddNode(translationTransformNode)
    translationTransformNode.SetMatrixTransformToParent(translationTransformMatrix)

    tinyVolumeNode.SetAndObserveTransformNodeID(translationTransformNode.GetID())
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (49,49,23), (224.3439, 223.7890, -135.25),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 94)

    # Volume source with isotropic spacing
    tinyVolumeNode.SetAndObserveTransformNodeID(None)
    geometryWidget.setIsotropicSpacing(True)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (23,23,23), (248.8439, 248.2890, -123.75),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 414)

    # Volume source with oversampling
    geometryWidget.setIsotropicSpacing(False)
    geometryWidget.setOversamplingFactor(2.0)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (24.5, 24.5, 11.5), (261.0939, 260.5390, -129.5),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 751)
    slicer.util.delayDisplay('Volume source cases - OK')

    # Segmentation source with binary labelmap master
    geometryWidget.setOversamplingFactor(1.0)
    geometryWidget.setSourceNode(tinySegmentationNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (49,49,23), (248.8439, 248.2890, -123.75),
        [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

    # Segmentation source with closed surface master
    tinySegmentationNode.GetSegmentation().SetConversionParameter('Smoothing factor', '0.0')
    self.assertTrue(tinySegmentationNode.GetSegmentation().CreateRepresentation(closedSurfaceReprName))
    tinySegmentationNode.GetSegmentation().SetMasterRepresentationName(closedSurfaceReprName)
    tinySegmentationNode.Modified() # Trigger re-calculation of geometry (only generic Modified event is observed)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (1,1,1), (-167.156, -217.711, -135.75),
        [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 5223846)
    slicer.util.delayDisplay('Segmentation source cases - OK')

    # Model source with no transform
    outputModelHierarchy = slicer.vtkMRMLModelHierarchyNode()
    slicer.mrmlScene.AddNode(outputModelHierarchy)
    success = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.ExportVisibleSegmentsToModelHierarchy(
      tinySegmentationNode, outputModelHierarchy )
    self.assertTrue(success)
    modelNode = slicer.util.getNode('Body_Contour')
    geometryWidget.setSourceNode(modelNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (1,1,1), (-167.156, -217.711, -135.75),
        [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 5223846)

    # Transformed model source
    rotationTransform = vtk.vtkTransform()
    rotationTransform.RotateX(45)
    rotationTransformMatrix = vtk.vtkMatrix4x4()
    rotationTransform.GetMatrix(rotationTransformMatrix)
    rotationTransformNode = slicer.vtkMRMLLinearTransformNode()
    rotationTransformNode.SetName('TestRotation')
    slicer.mrmlScene.AddNode(rotationTransformNode)
    rotationTransformNode.SetMatrixTransformToParent(rotationTransformMatrix)

    modelNode.SetAndObserveTransformNodeID(rotationTransformNode.GetID())
    modelNode.Modified()
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (1,1,1), (-167.156, -58.6623, -249.228),
        [[0.0, 0.0, 1.0], [-0.7071, -0.7071, 0.0], [0.7071, -0.7071, 0.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 5221241)

    # ROI source
    roiNode = slicer.vtkMRMLAnnotationROINode()
    roiNode.SetName('SourceROI')
    slicer.mrmlScene.AddNode(roiNode)
    roiNode.UnRegister(None)
    xyz = [0]*3
    center = [0]*3
    slicer.vtkMRMLSliceLogic.GetVolumeRASBox(tinyVolumeNode, xyz, center)
    radius = map(lambda x: x/2.0, xyz)
    roiNode.SetXYZ(center)
    roiNode.SetRadiusXYZ(radius)
    geometryWidget.setSourceNode(roiNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (1,1,1), (-216.156, -217.711, -135.75),
        [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 5223846)
    slicer.util.delayDisplay('Model and ROI source cases - OK')

    slicer.util.delayDisplay('Segmentation geometry widget test passed')
  def TestSection_2_qMRMLSegmentationGeometryWidget(self):
    logging.info('Test section 2: qMRMLSegmentationGeometryWidget')

    import vtkSegmentationCore
    binaryLabelmapReprName = vtkSegmentationCore.vtkSegmentationConverter.GetBinaryLabelmapRepresentationName()
    closedSurfaceReprName = vtkSegmentationCore.vtkSegmentationConverter.GetClosedSurfaceRepresentationName()

    # Use MRHead and Tinypatient for testing
    import SampleData
    sampleDataLogic = SampleData.SampleDataLogic()
    mrVolumeNode = sampleDataLogic.downloadMRHead()
    [tinyVolumeNode, tinySegmentationNode] = sampleDataLogic.downloadSample('TinyPatient')

    # Convert MRHead to oriented image data
    import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic
    mrOrientedImageData = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.CreateOrientedImageDataFromVolumeNode(mrVolumeNode)
    mrOrientedImageData.UnRegister(None)

    # Create segmentation node with binary labelmap master and one segment with MRHead geometry
    segmentationNode = slicer.vtkMRMLSegmentationNode()
    segmentationNode.GetSegmentation().SetMasterRepresentationName(binaryLabelmapReprName)
    geometryStr = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(mrOrientedImageData)
    segmentationNode.GetSegmentation().SetConversionParameter(
      vtkSegmentationCore.vtkSegmentationConverter.GetReferenceImageGeometryParameterName(), geometryStr)
    slicer.mrmlScene.AddNode(segmentationNode)
    threshold = vtk.vtkImageThreshold()
    threshold.SetInputData(mrOrientedImageData)
    threshold.ThresholdByUpper(16.0)
    threshold.SetInValue(1)
    threshold.SetOutValue(0)
    threshold.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR)
    threshold.Update()
    segmentOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()
    segmentOrientedImageData.DeepCopy(threshold.GetOutput())
    mrImageToWorldMatrix = vtk.vtkMatrix4x4()
    mrOrientedImageData.GetImageToWorldMatrix(mrImageToWorldMatrix)
    segmentOrientedImageData.SetImageToWorldMatrix(mrImageToWorldMatrix)
    segment = vtkSegmentationCore.vtkSegment()
    segment.SetName('Brain')
    segment.SetColor(0.0,0.0,1.0)
    segment.AddRepresentation(binaryLabelmapReprName, segmentOrientedImageData)
    segmentationNode.GetSegmentation().AddSegment(segment)

    # Create geometry widget
    geometryWidget = slicer.qMRMLSegmentationGeometryWidget()
    geometryWidget.setSegmentationNode(segmentationNode)
    geometryWidget.editEnabled = True
    geometryImageData = vtkSegmentationCore.vtkOrientedImageData() # To contain the output later

    # Volume source with no transforms
    geometryWidget.setSourceNode(tinyVolumeNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (49,49,23), (248.8439, 248.2890, -123.75),
        [[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]))
    slicer.util.delayDisplay('Volume source with no transforms - OK')

    # Transformed volume source
    translationTransformMatrix = vtk.vtkMatrix4x4()
    translationTransformMatrix.SetElement(0,3,24.5)
    translationTransformMatrix.SetElement(1,3,24.5)
    translationTransformMatrix.SetElement(2,3,11.5)
    translationTransformNode = slicer.vtkMRMLLinearTransformNode()
    translationTransformNode.SetName('TestTranslation')
    slicer.mrmlScene.AddNode(translationTransformNode)
    translationTransformNode.SetMatrixTransformToParent(translationTransformMatrix)

    tinyVolumeNode.SetAndObserveTransformNodeID(translationTransformNode.GetID())
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (49,49,23), (224.3439, 223.7890, -135.25),
        [[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]))
    slicer.util.delayDisplay('Transformed volume source - OK')

    # Volume source with isotropic spacing
    tinyVolumeNode.SetAndObserveTransformNodeID(None)
    geometryWidget.setIsotropicSpacing(True)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (23,23,23), (248.8439, 248.2890, -123.75),
        [[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]))
    slicer.util.delayDisplay('Volume source with isotropic spacing - OK')

    # Volume source with oversampling
    geometryWidget.setIsotropicSpacing(False)
    geometryWidget.setOversamplingFactor(2.0)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (24.5, 24.5, 11.5), (261.0939, 260.5390, -129.5),
        [[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]))
    slicer.util.delayDisplay('Volume source with oversampling - OK')

    # Segmentation source with binary labelmap master
    geometryWidget.setOversamplingFactor(1.0)
    geometryWidget.setSourceNode(tinySegmentationNode)
    geometryWidget.geometryImageData(geometryImageData)
    self.assertTrue(self.compareOutputGeometry(geometryImageData,
        (49,49,23), (248.8439, 248.2890, -123.75),
        [[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]))
    slicer.util.delayDisplay('Segmentation source with binary labelmap master - OK')

    # Segmentation source with closed surface master
    tinySegmentationNode.GetSegmentation().SetConversionParameter('Smoothing factor', '0.0')
    self.assertTrue(tinySegmentationNode.GetSegmentation().CreateRepresentation(closedSurfaceReprName))
    tinySegmentationNode.GetSegmentation().SetMasterRepresentationName(closedSurfaceReprName)
    tinySegmentationNode.Modified() # Trigger re-calculation of geometry (only generic Modified event is observed)
    geometryWidget.geometryImageData(geometryImageData)
    # Manually resample and check if the output is non-empty
    # Note: This is done for all poly data based geometry calculations below
    #TODO: Come up with proper geometry baselines for these too
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertTrue(self.imageDataContainsData(geometryImageData))
    slicer.util.delayDisplay('Segmentation source with closed surface master - OK')

    # Model source with no transform
    outputModelHierarchy = slicer.vtkMRMLModelHierarchyNode()
    slicer.mrmlScene.AddNode(outputModelHierarchy)
    success = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.ExportVisibleSegmentsToModelHierarchy(
      tinySegmentationNode, outputModelHierarchy )
    self.assertTrue(success)
    modelNode = slicer.util.getNode('Body_Contour')
    geometryWidget.setSourceNode(modelNode)
    geometryWidget.geometryImageData(geometryImageData)
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertTrue(self.imageDataContainsData(geometryImageData))
    slicer.util.delayDisplay('Model source with no transform - OK')

    # Transformed model source
    rotationTransform = vtk.vtkTransform()
    rotationTransform.RotateX(45)
    rotationTransformMatrix = vtk.vtkMatrix4x4()
    rotationTransform.GetMatrix(rotationTransformMatrix)
    rotationTransformNode = slicer.vtkMRMLLinearTransformNode()
    rotationTransformNode.SetName('TestRotation')
    slicer.mrmlScene.AddNode(rotationTransformNode)
    rotationTransformNode.SetMatrixTransformToParent(rotationTransformMatrix)

    modelNode.SetAndObserveTransformNodeID(rotationTransformNode.GetID())
    modelNode.Modified()
    geometryWidget.geometryImageData(geometryImageData)
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertTrue(self.imageDataContainsData(geometryImageData))
    slicer.util.delayDisplay('Transformed model source - OK')

    # ROI source
    roiNode = slicer.vtkMRMLAnnotationROINode()
    roiNode.SetName('SourceROI')
    slicer.mrmlScene.AddNode(roiNode)
    roiNode.UnRegister(None)
    xyz = [0]*3
    center = [0]*3
    slicer.vtkMRMLSliceLogic.GetVolumeRASBox(tinyVolumeNode, xyz, center)
    radius = map(lambda x: x/2.0, xyz)
    roiNode.SetXYZ(center)
    roiNode.SetRadiusXYZ(radius)
    geometryWidget.setSourceNode(roiNode)
    geometryWidget.geometryImageData(geometryImageData)
    vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
      segmentOrientedImageData, geometryImageData, geometryImageData, False, True)
    self.assertTrue(self.imageDataContainsData(geometryImageData))
    slicer.util.delayDisplay('ROI source - OK')

    slicer.util.delayDisplay('Segmentation geometry widget test passed')
    def TestSection_03_qMRMLSegmentationGeometryWidget(self):
        logging.info('Test section 2: qMRMLSegmentationGeometryWidget')

        import vtkSegmentationCore
        binaryLabelmapReprName = vtkSegmentationCore.vtkSegmentationConverter.GetBinaryLabelmapRepresentationName(
        )
        closedSurfaceReprName = vtkSegmentationCore.vtkSegmentationConverter.GetClosedSurfaceRepresentationName(
        )

        # Use MRHead and Tinypatient for testing
        import SampleData
        mrVolumeNode = SampleData.downloadSample("MRHead")
        [tinyVolumeNode,
         tinySegmentationNode] = SampleData.downloadSamples('TinyPatient')

        # Convert MRHead to oriented image data
        import vtkSlicerSegmentationsModuleLogicPython as vtkSlicerSegmentationsModuleLogic
        mrOrientedImageData = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.CreateOrientedImageDataFromVolumeNode(
            mrVolumeNode)
        mrOrientedImageData.UnRegister(None)

        # Create segmentation node with binary labelmap master and one segment with MRHead geometry
        segmentationNode = slicer.mrmlScene.AddNewNodeByClass(
            'vtkMRMLSegmentationNode')
        segmentationNode.GetSegmentation().SetMasterRepresentationName(
            binaryLabelmapReprName)
        geometryStr = vtkSegmentationCore.vtkSegmentationConverter.SerializeImageGeometry(
            mrOrientedImageData)
        segmentationNode.GetSegmentation().SetConversionParameter(
            vtkSegmentationCore.vtkSegmentationConverter.
            GetReferenceImageGeometryParameterName(), geometryStr)

        threshold = vtk.vtkImageThreshold()
        threshold.SetInputData(mrOrientedImageData)
        threshold.ThresholdByUpper(16.0)
        threshold.SetInValue(1)
        threshold.SetOutValue(0)
        threshold.SetOutputScalarType(vtk.VTK_UNSIGNED_CHAR)
        threshold.Update()
        segmentOrientedImageData = vtkSegmentationCore.vtkOrientedImageData()
        segmentOrientedImageData.DeepCopy(threshold.GetOutput())
        mrImageToWorldMatrix = vtk.vtkMatrix4x4()
        mrOrientedImageData.GetImageToWorldMatrix(mrImageToWorldMatrix)
        segmentOrientedImageData.SetImageToWorldMatrix(mrImageToWorldMatrix)
        segment = vtkSegmentationCore.vtkSegment()
        segment.SetName('Brain')
        segment.SetColor(0.0, 0.0, 1.0)
        segment.AddRepresentation(binaryLabelmapReprName,
                                  segmentOrientedImageData)
        segmentationNode.GetSegmentation().AddSegment(segment)

        # Create geometry widget
        geometryWidget = slicer.qMRMLSegmentationGeometryWidget()
        geometryWidget.setSegmentationNode(segmentationNode)
        geometryWidget.editEnabled = True
        geometryImageData = vtkSegmentationCore.vtkOrientedImageData(
        )  # To contain the output later

        # Volume source with no transforms
        geometryWidget.setSourceNode(tinyVolumeNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (49, 49, 23), (248.8439, 248.2890, -123.75),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

        # Transformed volume source
        translationTransformMatrix = vtk.vtkMatrix4x4()
        translationTransformMatrix.SetElement(0, 3, 24.5)
        translationTransformMatrix.SetElement(1, 3, 24.5)
        translationTransformMatrix.SetElement(2, 3, 11.5)
        translationTransformNode = slicer.vtkMRMLLinearTransformNode()
        translationTransformNode.SetName('TestTranslation')
        slicer.mrmlScene.AddNode(translationTransformNode)
        translationTransformNode.SetMatrixTransformToParent(
            translationTransformMatrix)

        tinyVolumeNode.SetAndObserveTransformNodeID(
            translationTransformNode.GetID())
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (49, 49, 23), (224.3439, 223.7890, -135.25),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 94)

        # Volume source with isotropic spacing
        tinyVolumeNode.SetAndObserveTransformNodeID(None)
        geometryWidget.setIsotropicSpacing(True)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (23, 23, 23), (248.8439, 248.2890, -123.75),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 414)

        # Volume source with oversampling
        geometryWidget.setIsotropicSpacing(False)
        geometryWidget.setOversamplingFactor(2.0)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (24.5, 24.5, 11.5),
                (261.0939, 260.5390, -129.5),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 751)
        slicer.util.delayDisplay('Volume source cases - OK')

        # Segmentation source with binary labelmap master
        geometryWidget.setOversamplingFactor(1.0)
        geometryWidget.setSourceNode(tinySegmentationNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (49, 49, 23), (248.8439, 248.2890, -123.75),
                [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData), 92)

        # Segmentation source with closed surface master
        tinySegmentationNode.GetSegmentation().SetConversionParameter(
            'Smoothing factor', '0.0')
        self.assertTrue(
            tinySegmentationNode.GetSegmentation().CreateRepresentation(
                closedSurfaceReprName))
        tinySegmentationNode.GetSegmentation().SetMasterRepresentationName(
            closedSurfaceReprName)
        tinySegmentationNode.Modified(
        )  # Trigger re-calculation of geometry (only generic Modified event is observed)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (-167.156, -217.711, -135.75),
                [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5223846)
        slicer.util.delayDisplay('Segmentation source cases - OK')

        # Model source with no transform
        shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(
            slicer.mrmlScene)
        outputFolderId = shNode.CreateFolderItem(shNode.GetSceneItemID(),
                                                 'ModelsFolder')
        success = vtkSlicerSegmentationsModuleLogic.vtkSlicerSegmentationsModuleLogic.ExportVisibleSegmentsToModels(
            tinySegmentationNode, outputFolderId)
        self.assertTrue(success)
        modelNode = slicer.util.getNode('Body_Contour')
        geometryWidget.setSourceNode(modelNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (-167.156, -217.711, -135.75),
                [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5223846)

        # Transformed model source
        rotationTransform = vtk.vtkTransform()
        rotationTransform.RotateX(45)
        rotationTransformMatrix = vtk.vtkMatrix4x4()
        rotationTransform.GetMatrix(rotationTransformMatrix)
        rotationTransformNode = slicer.vtkMRMLLinearTransformNode()
        rotationTransformNode.SetName('TestRotation')
        slicer.mrmlScene.AddNode(rotationTransformNode)
        rotationTransformNode.SetMatrixTransformToParent(
            rotationTransformMatrix)

        modelNode.SetAndObserveTransformNodeID(rotationTransformNode.GetID())
        modelNode.Modified()
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (-167.156, -58.6623, -249.228),
                [[0.0, 0.0, 1.0], [-0.7071, -0.7071, 0.0],
                 [0.7071, -0.7071, 0.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5221241)

        # ROI source
        roiNode = slicer.vtkMRMLAnnotationROINode()
        roiNode.SetName('SourceROI')
        slicer.mrmlScene.AddNode(roiNode)
        roiNode.UnRegister(None)
        xyz = [0] * 3
        center = [0] * 3
        slicer.vtkMRMLSliceLogic.GetVolumeRASBox(tinyVolumeNode, xyz, center)
        radius = [x / 2.0 for x in xyz]
        roiNode.SetXYZ(center)
        roiNode.SetRadiusXYZ(radius)
        geometryWidget.setSourceNode(roiNode)
        geometryWidget.geometryImageData(geometryImageData)
        self.assertTrue(
            self.compareOutputGeometry(
                geometryImageData, (1, 1, 1), (-216.156, -217.711, -135.75),
                [[0.0, 0.0, 1.0], [-1.0, 0.0, 0.0], [0.0, -1.0, 0.0]]))
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
            segmentOrientedImageData, geometryImageData, geometryImageData,
            False, True)
        self.assertEqual(self.getForegroundVoxelCount(geometryImageData),
                         5223846)
        slicer.util.delayDisplay('Model and ROI source cases - OK')

        slicer.util.delayDisplay('Segmentation geometry widget test passed')
Пример #22
0
    def setup(self):
        # Instantiate and connect widgets ...
        ScriptedLoadableModuleWidget.setup(self)

        #self.logic = CIP_CalciumScoringLogic()

        #
        # Parameters Area
        #
        parametersCollapsibleButton = ctk.ctkCollapsibleButton()
        parametersCollapsibleButton.text = "Parameters"
        self.layout.addWidget(parametersCollapsibleButton)

        # Layout within the dummy collapsible button
        parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)

        #
        # target volume selector
        #
        self.inputSelector = slicer.qMRMLNodeComboBox()
        self.inputSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
        self.inputSelector.addEnabled = False
        self.inputSelector.removeEnabled = False
        self.inputSelector.noneEnabled = False
        self.inputSelector.showHidden = False
        self.inputSelector.showChildNodeTypes = False
        self.inputSelector.setMRMLScene( slicer.mrmlScene )
        self.inputSelector.setToolTip( "Pick the input to the algorithm." )
        parametersFormLayout.addRow("Target Volume: ", self.inputSelector)
        self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onVolumeChanged)
        self.volumeNode = self.inputSelector.currentNode()
        
        #
        # Calcination type
        #
        self.calcinationTypeBox = qt.QComboBox()
        self.calcinationTypeBox.addItem("Heart")
        self.calcinationTypeBox.addItem("Aorta")
        parametersFormLayout.addRow("Calcination Region", self.calcinationTypeBox)
        self.calcinationTypeBox.connect("currentIndexChanged(int)", self.onTypeChanged)

        self.ThresholdRange = ctk.ctkRangeWidget()
        self.ThresholdRange.minimum = 0
        self.ThresholdRange.maximum = 3000
        self.ThresholdRange.setMinimumValue(self.ThresholdMin)
        self.ThresholdRange.setMaximumValue(self.ThresholdMax)
        self.ThresholdRange.connect("minimumValueChanged(double)", self.onThresholdMinChanged)
        self.ThresholdRange.connect("maximumValueChanged(double)", self.onThresholdMaxChanged)
        parametersFormLayout.addRow("Threshold Value", self.ThresholdRange)
        self.ThresholdRange.setMinimumValue(self.ThresholdMin)
        self.ThresholdRange.setMaximumValue(self.ThresholdMax)

        self.LesionSizeRange= ctk.ctkRangeWidget()
        self.LesionSizeRange.minimum = 1
        self.LesionSizeRange.maximum = 1000
        self.LesionSizeRange.setMinimumValue(self.MinimumLesionSize)
        self.LesionSizeRange.setMaximumValue(self.MaximumLesionSize)
        self.LesionSizeRange.connect("minimumValueChanged(double)", self.onMinSizeChanged)
        self.LesionSizeRange.connect("maximumValueChanged(double)", self.onMaxSizeChanged)
        parametersFormLayout.addRow("Lesion Size (mm^3)", self.LesionSizeRange)
        self.LesionSizeRange.setMinimumValue(self.MinimumLesionSize)
        self.LesionSizeRange.setMaximumValue(self.MaximumLesionSize)

        self.scoreField = qt.QLineEdit()
        self.scoreField.setText(self.totalScore)
        parametersFormLayout.addRow("Total Score", self.scoreField)
        
        #
        # Select table
        #
        self.selectLabels = qt.QTableWidget()
        self.selectLabels.horizontalHeader().hide()
        self.selectLabels.verticalHeader().hide()
        self.selectLabels.setColumnCount(2)
        self.selectLabels.itemClicked.connect(self.handleItemClicked)
        parametersFormLayout.addRow("", self.selectLabels)

        #
        # ROI Area
        #
        self.roiCollapsibleButton = ctk.ctkCollapsibleButton()
        self.roiCollapsibleButton.text = "Heart ROI"
        self.roiCollapsibleButton.setChecked(False)
        self.layout.addWidget(self.roiCollapsibleButton)

        # Layout within the dummy collapsible button
        roiFormLayout = qt.QFormLayout(self.roiCollapsibleButton)

        #
        # ROI
        #
        self.ROIWidget = slicer.qMRMLAnnotationROIWidget()
        self.roiNode = slicer.vtkMRMLAnnotationROINode()
        slicer.mrmlScene.AddNode(self.roiNode)
        self.ROIWidget.setMRMLAnnotationROINode(self.roiNode)
        roiFormLayout.addRow("", self.ROIWidget)
        self.roiNode.AddObserver("ModifiedEvent", self.onROIChangedEvent, 1)

        # Add vertical spacer
        self.layout.addStretch(1)

        # Add temp nodes
        self.croppedNode=slicer.vtkMRMLScalarVolumeNode()
        self.croppedNode.SetHideFromEditors(1)
        slicer.mrmlScene.AddNode(self.croppedNode)
        self.labelsNode=slicer.vtkMRMLLabelMapVolumeNode()
        slicer.mrmlScene.AddNode(self.labelsNode)
        
        if self.inputSelector.currentNode():
            self.onVolumeChanged(self.inputSelector.currentNode())
            self.createModels()
Пример #23
0
  def refineLandmark(self, state):
    """Refine the specified landmark"""
    # Refine landmark, or if none, do nothing
    #     Crop images around the fiducial
    #     Affine registration of the cropped images
    #     Transform the fiducial using the transformation
    #
    # No need to take into account the current transformation because landmarks are in World RAS
    timing = False
    if self.VerboseMode == "Verbose":
      timing = True

    if state.logic.cropLogic is None:
      print("Cannot refine landmarks. CropVolume module is not available.")

    if state.fixed == None or state.moving == None or state.fixedFiducials == None or  state.movingFiducials == None or state.currentLandmarkName == None:
      print "Cannot refine landmarks. Images or landmarks not selected."
      return

    print ("Refining landmark " + state.currentLandmarkName) + " using " + self.name

    start = time.time()

    volumes = (state.fixed, state.moving)
    (fixedVolume, movingVolume) = volumes

    slicer.mrmlScene.StartState(slicer.mrmlScene.BatchProcessState)
    landmarks = state.logic.landmarksForVolumes(volumes)

    cvpn = slicer.vtkMRMLCropVolumeParametersNode()
    cvpn.SetInterpolationMode(1)
    cvpn.SetVoxelBased(1)
    fixedPoint = [0,]*3
    movingPoint = [0,]*3

    (fixedFiducial, movingFiducial) = landmarks[state.currentLandmarkName]

    (fixedList,fixedIndex) = fixedFiducial
    (movingList, movingIndex) = movingFiducial

    # define an roi for the fixed
    if timing: roiStart = time.time()
    roiFixed = slicer.vtkMRMLAnnotationROINode()
    slicer.mrmlScene.AddNode(roiFixed)

    fixedList.GetNthFiducialPosition(fixedIndex,fixedPoint)
    roiFixed.SetDisplayVisibility(0)
    roiFixed.SelectableOff()
    roiFixed.SetXYZ(fixedPoint)
    roiFixed.SetRadiusXYZ(30, 30, 30)

    # crop the fixed. note we hide the display node temporarily to avoid the automated
    # window level calculation on temporary nodes created by cloning
    cvpn.SetROINodeID( roiFixed.GetID() )
    cvpn.SetInputVolumeNodeID( fixedVolume.GetID() )
    fixedDisplayNode = fixedVolume.GetDisplayNode()
    fixedVolume.SetAndObserveDisplayNodeID('This is not a valid DisplayNode ID')
    if timing: roiEnd = time.time()
    if timing: cropStart = time.time()
    state.logic.cropLogic.Apply( cvpn )
    if timing: cropEnd = time.time()
    croppedFixedVolume = slicer.mrmlScene.GetNodeByID( cvpn.GetOutputVolumeNodeID() )
    fixedVolume.SetAndObserveDisplayNodeID(fixedDisplayNode.GetID())

    # define an roi for the moving
    if timing: roi2Start = time.time()
    roiMoving = slicer.vtkMRMLAnnotationROINode()
    slicer.mrmlScene.AddNode(roiMoving)

    movingList.GetNthFiducialPosition(movingIndex,movingPoint)
    roiMoving.SetDisplayVisibility(0)
    roiMoving.SelectableOff()
    roiMoving.SetXYZ(movingPoint)
    if self.LocalBRAINSFitMode == "Small":
      roiMoving.SetRadiusXYZ(45, 45, 45)
    else:
      roiMoving.SetRadiusXYZ(60, 60, 60)

    # crop the moving. note we hide the display node temporarily to avoid the automated
    # window level calculation on temporary nodes created by cloning
    cvpn.SetROINodeID( roiMoving.GetID() )
    cvpn.SetInputVolumeNodeID( movingVolume.GetID() )
    movingDisplayNode = movingVolume.GetDisplayNode()
    movingVolume.SetAndObserveDisplayNodeID('This is not a valid DisplayNode ID')
    if timing: roi2End = time.time()
    if timing: crop2Start = time.time()
    state.logic.cropLogic.Apply( cvpn )
    if timing: crop2End = time.time()
    croppedMovingVolume = slicer.mrmlScene.GetNodeByID( cvpn.GetOutputVolumeNodeID() )
    movingVolume.SetAndObserveDisplayNodeID(movingDisplayNode.GetID())

    if timing: print 'Time to set up fixed ROI was ' + str(roiEnd - roiStart) + ' seconds'
    if timing: print 'Time to set up moving ROI was ' + str(roi2End - roi2Start) + ' seconds'
    if timing: print 'Time to crop fixed volume ' + str(cropEnd - cropStart) + ' seconds'
    if timing: print 'Time to crop moving volume ' + str(crop2End - crop2Start) + ' seconds'

    #
    transform = slicer.vtkMRMLLinearTransformNode()
    slicer.mrmlScene.AddNode(transform)
    matrix = vtk.vtkMatrix4x4()

    # define the registration parameters
    minPixelSpacing = min(croppedFixedVolume.GetSpacing())
    parameters = {}
    parameters['fixedVolume'] = croppedFixedVolume.GetID()
    parameters['movingVolume'] = croppedMovingVolume.GetID()
    parameters['linearTransform'] = transform.GetID()
    parameters['useRigid'] = True
    parameters['initializeTransformMode'] = 'useGeometryAlign';
    parameters['samplingPercentage'] = 0.2
    parameters['minimumStepLength'] = 0.1 * minPixelSpacing
    parameters['maximumStepLength'] = minPixelSpacing

    # run the registration
    if timing: regStart = time.time()
    slicer.cli.run(slicer.modules.brainsfit, None, parameters, wait_for_completion=True)
    if timing: regEnd = time.time()
    if timing: print 'Time for local registration ' + str(regEnd - regStart) + ' seconds'

    # apply the local transform to the landmark
    #print transform
    if timing: resultStart = time.time()
    transform.GetMatrixTransformToWorld(matrix)
    matrix.Invert()
    tp = [0,]*4
    tp = matrix.MultiplyPoint(fixedPoint + [1,])
    #print fixedPoint, movingPoint, tp[:3]

    movingList.SetNthFiducialPosition(movingIndex, tp[0], tp[1], tp[2])
    if timing: resultEnd = time.time()
    if timing: print 'Time for transforming landmark was ' + str(resultEnd - resultStart) + ' seconds'

    # clean up cropped volmes, need to reset the foreground/background display before we delete it
    if timing: cleanUpStart = time.time()
    slicer.mrmlScene.RemoveNode(croppedFixedVolume)
    slicer.mrmlScene.RemoveNode(croppedMovingVolume)
    slicer.mrmlScene.RemoveNode(roiFixed)
    slicer.mrmlScene.RemoveNode(roiMoving)
    slicer.mrmlScene.RemoveNode(transform)
    roiFixed = None
    roiMoving = None
    transform = None
    matrix = None
    if timing: cleanUpEnd = time.time()
    if timing: print 'Cleanup took ' + str(cleanUpEnd - cleanUpStart) + ' seconds'

    end = time.time()
    print 'Refined landmark ' + state.currentLandmarkName + ' in ' + str(end - start) + ' seconds'

    slicer.mrmlScene.EndState(slicer.mrmlScene.BatchProcessState)
Пример #24
0
    def setup(self):
        # Instantiate and connect widgets ...
        ScriptedLoadableModuleWidget.setup(self)

        #self.logic = CIP_CalciumScoringLogic()

        #
        # Parameters Area
        #
        parametersCollapsibleButton = ctk.ctkCollapsibleButton()
        parametersCollapsibleButton.text = "Parameters"
        self.layout.addWidget(parametersCollapsibleButton)

        # Layout within the dummy collapsible button
        parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)

        #
        # target volume selector
        #
        self.inputSelector = slicer.qMRMLNodeComboBox()
        self.inputSelector.nodeTypes = ( ("vtkMRMLScalarVolumeNode"), "" )
        self.inputSelector.addEnabled = False
        self.inputSelector.removeEnabled = False
        self.inputSelector.noneEnabled = False
        self.inputSelector.showHidden = False
        self.inputSelector.showChildNodeTypes = False
        self.inputSelector.setMRMLScene( slicer.mrmlScene )
        self.inputSelector.setToolTip( "Pick the input to the algorithm." )
        parametersFormLayout.addRow("Target Volume: ", self.inputSelector)
        self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onVolumeChanged)
        self.volumeNode = self.inputSelector.currentNode()
        
        #
        # calcification type
        #
#        self.calcificationTypeBox = qt.QComboBox()
#        self.calcificationTypeBox.addItem("Heart")
#        self.calcificationTypeBox.addItem("Aorta")
#        parametersFormLayout.addRow("Region", self.calcificationTypeBox)
#        self.calcificationTypeBox.connect("currentIndexChanged(int)", self.onTypeChanged)

        self.ThresholdRange = ctk.ctkRangeWidget()
        self.ThresholdRange.minimum = 0
        self.ThresholdRange.maximum = 2000
        self.ThresholdRange.setMinimumValue(self.ThresholdMin)
        self.ThresholdRange.setMaximumValue(self.ThresholdMax)
        self.ThresholdRange.connect("minimumValueChanged(double)", self.onThresholdMinChanged)
        self.ThresholdRange.connect("maximumValueChanged(double)", self.onThresholdMaxChanged)
        parametersFormLayout.addRow("Threshold Value", self.ThresholdRange)
        self.ThresholdRange.setMinimumValue(self.ThresholdMin)
        self.ThresholdRange.setMaximumValue(self.ThresholdMax)

        self.LesionSizeRange= ctk.ctkRangeWidget()
        self.LesionSizeRange.minimum = 0.5
        self.LesionSizeRange.maximum = 1000
        self.LesionSizeRange.setMinimumValue(self.MinimumLesionSize)
        self.LesionSizeRange.setMaximumValue(self.MaximumLesionSize)
        self.LesionSizeRange.connect("minimumValueChanged(double)", self.onMinSizeChanged)
        self.LesionSizeRange.connect("maximumValueChanged(double)", self.onMaxSizeChanged)
        parametersFormLayout.addRow("Lesion Size (mm^3)", self.LesionSizeRange)
        self.LesionSizeRange.setMinimumValue(self.MinimumLesionSize)
        self.LesionSizeRange.setMaximumValue(self.MaximumLesionSize)

        self.scoreField=dict()
        for sr in self.summary_reports:
          self.scoreField[sr] = qt.QLineEdit()
          self.scoreField[sr].setText(0)
          parametersFormLayout.addRow("Total "+sr, self.scoreField[sr])
        
        
        #
        # Update button and Select Table
        #
        
        self.updateButton = qt.QPushButton("Update")
        self.updateButton.toolTip = "Update calcium score computation"
        self.updateButton.enabled = True
        self.updateButton.setFixedSize(100, 50)
        #parametersFormLayout.addRow("", self.updateButton)
        
        self.updateButton.connect('clicked()', self.onUpdate)
        
        #
        # Select table
        #
        self.selectLabels = qt.QTableWidget()
        #self.selectLabels.horizontalHeader().hide()
        self.selectLabels.verticalHeader().hide()
        self.selectLabels.setColumnCount(6)
        self.selectLabels.itemClicked.connect(self.handleItemClicked)
        
        #Add row with columns name
        col_names=["","Agatston Score","Mass Score","Volume (mm^3)","Mean HU","Max HU"]
        self.selectLabels.setHorizontalHeaderLabels(col_names)
        
        parametersFormLayout.addRow(self.updateButton, self.selectLabels)


        #
        # Save Widget Area
        #

        #self.saveCollapsibleButton = ctk.ctkCollapsibleButton()
        #self.saveCollapsibleButton.text = "Saving"
        #self.layout.addWidget(self.saveCollapsibleButton)

        self.reportsWidget = CaseReportsWidget(self.moduleName, self.columnsDict, parentWidget=self.parent)
        self.reportsWidget.setup()
        self.reportsWidget.showPrintButton(False)
        
        self.reportsWidget.addObservable(self.reportsWidget.EVENT_SAVE_BUTTON_CLICKED, self.onSaveReport)

        #
        # ROI Area
        #
        self.roiCollapsibleButton = ctk.ctkCollapsibleButton()
        self.roiCollapsibleButton.text = "ROI"
        self.roiCollapsibleButton.setChecked(False)
        self.layout.addWidget(self.roiCollapsibleButton)

        # Layout within the dummy collapsible button
        roiFormLayout = qt.QFormLayout(self.roiCollapsibleButton)

        #
        # ROI
        #
        self.ROIWidget = slicer.qMRMLAnnotationROIWidget()
        self.roiNode = slicer.vtkMRMLAnnotationROINode()
        slicer.mrmlScene.AddNode(self.roiNode)
        self.ROIWidget.setMRMLAnnotationROINode(self.roiNode)
        roiFormLayout.addRow("", self.ROIWidget)
        #self.roiNode.AddObserver("ModifiedEvent", self.onROIChangedEvent, 1)

        # Add vertical spacer
        self.layout.addStretch(1)

        # Add temp nodes
        self.croppedNode=slicer.vtkMRMLScalarVolumeNode()
        self.croppedNode.SetHideFromEditors(1)
        slicer.mrmlScene.AddNode(self.croppedNode)
        self.labelsNode=slicer.vtkMRMLLabelMapVolumeNode()
        slicer.mrmlScene.AddNode(self.labelsNode)
        
        if self.inputSelector.currentNode():
            self.onVolumeChanged(self.inputSelector.currentNode())