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 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()
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)
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')
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
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
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)
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
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')
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()
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)
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())