Ejemplo n.º 1
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)
        # Instantiate and connect widgets
        #
        # Interface
        #
        # Collapsible button -- Scene Description
        self.loadCollapsibleButton = ctk.ctkCollapsibleButton()
        self.loadCollapsibleButton.text = "Scene"
        self.layout.addWidget(self.loadCollapsibleButton)

        # Layout within the laplace collapsible button
        self.loadFormLayout = qt.QFormLayout(self.loadCollapsibleButton)

        # GLOBALS:
        self.image = None
        self.logic = EasyClipLogic()
        #--------------------------- List of Models --------------------------#

        treeView = slicer.qMRMLTreeView()
        treeView.setMRMLScene(slicer.app.mrmlScene())
        treeView.setSceneModelType('Displayable')
        treeView.sceneModel().setHorizontalHeaderLabels(["Models"])
        treeView.sortFilterProxyModel().nodeTypes = ['vtkMRMLModelNode']
        header = treeView.header()
        header.setResizeMode(0, qt.QHeaderView.Stretch)
        header.setVisible(True)
        self.loadFormLayout.addWidget(treeView)


        #------------------------ Compute Bounding Box ----------------------#
        buttonFrameBox = qt.QFrame(self.parent)
        buttonFrameBox.setLayout(qt.QHBoxLayout())
        self.loadFormLayout.addWidget(buttonFrameBox)

        self.computeBox = qt.QPushButton("Compute Bounding Box around all models")
        buttonFrameBox.layout().addWidget(self.computeBox)
        self.computeBox.connect('clicked()', self.onComputeBox)

        #--------------------------- Clipping Part --------------------------#

        # Collapsible button -- Clipping part
        self.loadCollapsibleButton = ctk.ctkCollapsibleButton()
        self.loadCollapsibleButton.text = "Clipping"
        self.layout.addWidget(self.loadCollapsibleButton)

        # Layout within the laplace collapsible button
        self.loadFormLayout = qt.QFormLayout(self.loadCollapsibleButton)

        #-------------------------- Buttons --------------------------#
        # CLIPPING BUTTONS

        self.red_plane_box = qt.QGroupBox("Red Slice Clipping")
        self.red_plane_box.setCheckable(True)
        self.red_plane_box.setChecked(False)
        self.red_plane_box.connect('clicked(bool)', self.redPlaneCheckBoxClicked)

        self.radio_red_Neg = qt.QRadioButton("Keep Down Arrow")
        self.radio_red_Neg.setIcon(qt.QIcon(":/Icons/RedSpaceNegative.png"))
        self.radio_red_Pos = qt.QRadioButton("Keep Top Arrow")
        self.radio_red_Pos.setIcon(qt.QIcon(":/Icons/RedSpacePositive.png"))

        vbox = qt.QHBoxLayout()
        vbox.addWidget(self.radio_red_Neg)
        vbox.addWidget(self.radio_red_Pos)
        vbox.addStretch(1)
        self.red_plane_box.setLayout(vbox)
        self.loadFormLayout.addWidget(self.red_plane_box)

        self.yellow_plane_box = qt.QGroupBox("Yellow Slice Clipping")
        self.yellow_plane_box.setCheckable(True)
        self.yellow_plane_box.setChecked(False)
        self.yellow_plane_box.connect('clicked(bool)', self.yellowPlaneCheckBoxClicked)

        self.radio_yellow_Neg= qt.QRadioButton("Keep Down Arrow")
        self.radio_yellow_Neg.setIcon(qt.QIcon(":/Icons/YellowSpaceNegative.png"))
        self.radio_yellow_Pos = qt.QRadioButton("Keep Top Arrow")
        self.radio_yellow_Pos.setIcon(qt.QIcon(":/Icons/YellowSpacePositive.png"))

        vbox = qt.QHBoxLayout()
        vbox.addWidget(self.radio_yellow_Neg)
        vbox.addWidget(self.radio_yellow_Pos)
        vbox.addStretch(1)
        self.yellow_plane_box.setLayout(vbox)
        self.loadFormLayout.addWidget(self.yellow_plane_box)


        self.green_plane_box = qt.QGroupBox("Green Slice Clipping")
        self.green_plane_box.setCheckable(True)
        self.green_plane_box.setChecked(False)
        self.green_plane_box.connect('clicked(bool)', self.greenPlaneCheckBoxClicked)

        self.radio_green_Neg= qt.QRadioButton("Keep Down Arrow")
        self.radio_green_Neg.setIcon(qt.QIcon(":/Icons/GreenSpaceNegative.png"))
        self.radio_green_Pos = qt.QRadioButton("Keep Top Arrow")
        self.radio_green_Pos.setIcon(qt.QIcon(":/Icons/GreenSpacePositive.png"))

        vbox = qt.QHBoxLayout()
        vbox.addWidget(self.radio_green_Neg)
        vbox.addWidget(self.radio_green_Pos)
        vbox.addStretch(1)
        self.green_plane_box.setLayout(vbox)
        self.loadFormLayout.addWidget(self.green_plane_box)

        buttonFrame = qt.QFrame(self.parent)
        buttonFrame.setLayout(qt.QHBoxLayout())
        self.loadFormLayout.addWidget(buttonFrame)

        self.ClippingButton = qt.QPushButton("Clipping")
        buttonFrame.layout().addWidget(self.ClippingButton)
        self.ClippingButton.connect('clicked()', self.ClippingButtonClicked)

        self.UndoButton = qt.QPushButton("Undo")
        buttonFrame.layout().addWidget(self.UndoButton)
        self.UndoButton.connect('clicked()', self.UndoButtonClicked)

        #--------------------------- Advanced Part --------------------------#
        #-------------------- Collapsible button -- Clipping part ----------------------#

        self.loadCollapsibleButton = ctk.ctkCollapsibleButton()
        self.loadCollapsibleButton.text = "Planes"
        self.layout.addWidget(self.loadCollapsibleButton)

        #-------------------- Layout within the laplace collapsible button ----------------------#
        self.loadFormLayout = qt.QFormLayout(self.loadCollapsibleButton)

        buttonFrame = qt.QFrame(self.parent)
        buttonFrame.setLayout(qt.QVBoxLayout())
        self.loadFormLayout.addWidget(buttonFrame)

        #-------------------- SAVE PLANE BUTTON ----------------------#

        save_plane = qt.QLabel("Save the planes you create as a txt file.")
        buttonFrame.layout().addWidget(save_plane)
        save = qt.QPushButton("Save plane")
        buttonFrame.layout().addWidget(save)
        save.connect('clicked(bool)', self.savePlane)

        #-------------------- READ PLANE BUTTON ----------------------#

        load_plane = qt.QLabel("Load the file with the plane you saved.")
        buttonFrame.layout().addWidget(load_plane)
        read = qt.QPushButton("Load plane")
        buttonFrame.layout().addWidget(read)
        read.connect('clicked(bool)', self.readPlane)

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

        #-------------------- onCloseScene ----------------------#
        slicer.mrmlScene.AddObserver(slicer.mrmlScene.EndCloseEvent, self.onCloseScene)
Ejemplo n.º 2
0
    def setup(self):
        #
        # Input frame
        #
        self.__inputFrame = ctk.ctkCollapsibleButton()
        self.__inputFrame.text = "Input"
        self.__inputFrame.collapsed = 0
        inputFrameLayout = qt.QFormLayout(self.__inputFrame)

        self.layout.addWidget(self.__inputFrame)

        # Active report node
        label = qt.QLabel('Report: ')
        self.__reportSelector = slicer.qMRMLNodeComboBox()
        self.__reportSelector.nodeTypes = ['vtkMRMLReportingReportNode']
        self.__reportSelector.setMRMLScene(slicer.mrmlScene)
        self.__reportSelector.addEnabled = 1
        self.__reportSelector.removeEnabled = 0

        inputFrameLayout.addRow(label, self.__reportSelector)

        self.__reportSelector.connect('mrmlSceneChanged(vtkMRMLScene*)',
                                      self.onMRMLSceneChanged)
        self.__reportSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                      self.onReportNodeChanged)

        # Volume being annotated (only one is allowed for the report)
        label = qt.QLabel(
            'NOTE: Only volumes loaded from DICOM can be annotated!')
        inputFrameLayout.addRow(label)
        label = qt.QLabel('Annotated volume: ')
        self.__volumeSelector = slicer.qMRMLNodeComboBox()
        self.__volumeSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
        # only allow volumes with the attribute DICOM.instanceUIDs
        self.__volumeSelector.addAttribute('vtkMRMLScalarVolumeNode',
                                           'DICOM.instanceUIDs')
        self.__volumeSelector.setMRMLScene(slicer.mrmlScene)
        self.__volumeSelector.addEnabled = False

        inputFrameLayout.addRow(label, self.__volumeSelector)

        self.__volumeSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                      self.onAnnotatedVolumeNodeChanged)
        self.__volumeSelector.connect('mrmlSceneChanged(vtkMRMLScene*)',
                                      self.onMRMLSceneChanged)

        #
        # Annotation frame -- vocabulary-based description of what is
        # being annotated/marked up in this report
        #
        self.__annotationsFrame = ctk.ctkCollapsibleButton()
        self.__annotationsFrame.text = "Annotation"
        self.__annotationsFrame.collapsed = 0
        annotationsFrameLayout = qt.QFormLayout(self.__annotationsFrame)

        self.layout.addWidget(self.__annotationsFrame)

        self.__defaultColorNode = self.__logic.GetDefaultColorNode()

        self.__toolsColor = EditColor(self.__annotationsFrame,
                                      colorNode=self.__defaultColorNode)

        #
        # Markup frame -- summary of all the markup elements contained in the
        # report
        #
        self.__markupFrame = ctk.ctkCollapsibleButton()
        self.__markupFrame.text = "Markup"
        self.__markupFrame.collapsed = 0
        markupFrameLayout = qt.QFormLayout(self.__markupFrame)

        self.layout.addWidget(self.__markupFrame)

        # Add a flag to switch between different tree view models
        self.__useNewTreeView = 1

        # Add the tree widget
        if self.__useNewTreeView == 1:
            self.__markupTreeView = slicer.modulewidget.qMRMLReportingTreeView(
            )
            self.__markupTreeView.sceneModelType = "DisplayableHierarchy"
        else:
            self.__markupTreeView = slicer.qMRMLTreeView()
            self.__markupTreeView.sceneModelType = "Displayable"
        self.__markupTreeView.setMRMLScene(self.__logic.GetMRMLScene())

        self.__markupSliceText = qt.QLabel()
        markupFrameLayout.addRow(self.__markupSliceText)
        markupFrameLayout.addRow(self.__markupTreeView)

        # Editor frame
        self.__editorFrame = ctk.ctkCollapsibleButton()
        self.__editorFrame.text = 'Segmentation'
        self.__editorFrame.collapsed = 0
        editorFrameLayout = qt.QFormLayout(self.__editorFrame)

        label = qt.QLabel('Segmentation volume: ')
        self.__segmentationSelector = slicer.qMRMLNodeComboBox()
        self.__segmentationSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
        self.__segmentationSelector.setMRMLScene(slicer.mrmlScene)
        self.__segmentationSelector.addEnabled = 1
        self.__segmentationSelector.noneEnabled = 1
        self.__segmentationSelector.removeEnabled = 0
        self.__segmentationSelector.showHidden = 0
        self.__segmentationSelector.showChildNodeTypes = 0
        self.__segmentationSelector.selectNodeUponCreation = 1
        self.__segmentationSelector.addAttribute('vtkMRMLScalarVolumeNode',
                                                 'LabelMap', 1)

        editorFrameLayout.addRow(label, self.__segmentationSelector)

        editorWidgetParent = slicer.qMRMLWidget()
        editorWidgetParent.setLayout(qt.QVBoxLayout())
        editorWidgetParent.setMRMLScene(slicer.mrmlScene)
        self.__editorWidget = EditorWidget(parent=editorWidgetParent,
                                           showVolumesFrame=False)
        self.__editorWidget.setup()
        self.__editorWidget.toolsColor.frame.setVisible(False)
        editorFrameLayout.addRow(editorWidgetParent)

        markupFrameLayout.addRow(self.__editorFrame)

        self.__segmentationSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                            self.onSegmentationNodeChanged)
        self.__segmentationSelector.connect('mrmlSceneChanged(vtkMRMLScene*)',
                                            self.onMRMLSceneChanged)

        # IO frame
        self.__ioFrame = ctk.ctkCollapsibleButton()
        self.__ioFrame.text = 'Import/Export'
        self.__ioFrame.collapsed = 1
        ioFrameLayout = qt.QGridLayout(self.__ioFrame)

        self.layout.addWidget(self.__ioFrame)

        # Buttons to save/load report using AIM XML serialization
        label = qt.QLabel('Export folder')
        self.__exportFolderPicker = ctk.ctkDirectoryButton()
        exportButton = qt.QPushButton('Export')
        exportButton.connect('clicked()', self.onReportExport)
        ioFrameLayout.addWidget(label, 0, 0)
        ioFrameLayout.addWidget(self.__exportFolderPicker, 0, 1)
        ioFrameLayout.addWidget(exportButton, 0, 2)

        label = qt.QLabel('AIM file to import')
        self.__aimFilePicker = qt.QPushButton('N/A')
        self.__aimFilePicker.connect('clicked()', self.onSelectAIMFile)
        button = qt.QPushButton('Import')
        button.connect('clicked()', self.onReportImport)
        ioFrameLayout.addWidget(label, 1, 0)
        ioFrameLayout.addWidget(self.__aimFilePicker, 1, 1)
        ioFrameLayout.addWidget(button, 1, 2)
        self.__importAIMFile = None

        self.__reportSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                      self.updateWidgets)
        self.__volumeSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                      self.updateWidgets)
        self.updateWidgets()

        self.layout.addStretch(1)

        self.__editorParameterNode = self.editUtil.getParameterNode()

        self.__editorParameterNode.AddObserver(
            vtk.vtkCommand.ModifiedEvent, self.onEditorParameterNodeChanged)
  def setup( self ):
    #
    # Input frame
    #
    self.__inputFrame = ctk.ctkCollapsibleButton()
    self.__inputFrame.text = "Input"
    self.__inputFrame.collapsed = 0
    inputFrameLayout = qt.QFormLayout(self.__inputFrame)
    
    self.layout.addWidget(self.__inputFrame)

    # Active report node
    label = qt.QLabel('Report: ')
    self.__reportSelector = slicer.qMRMLNodeComboBox()
    self.__reportSelector.nodeTypes =  ['vtkMRMLReportingReportNode']
    self.__reportSelector.setMRMLScene(slicer.mrmlScene)
    self.__reportSelector.addEnabled = 1
    self.__reportSelector.removeEnabled = 0
    
    inputFrameLayout.addRow(label, self.__reportSelector)

    self.__reportSelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onMRMLSceneChanged)
    self.__reportSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onReportNodeChanged)
 
    # Volume being annotated (only one is allowed for the report)
    label = qt.QLabel('NOTE: Only volumes loaded from DICOM can be annotated!')
    inputFrameLayout.addRow(label)
    label = qt.QLabel('Annotated volume: ')
    self.__volumeSelector = slicer.qMRMLNodeComboBox()
    self.__volumeSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
    # only allow volumes with the attribute DICOM.instanceUIDs
    self.__volumeSelector.addAttribute('vtkMRMLScalarVolumeNode','DICOM.instanceUIDs')
    self.__volumeSelector.setMRMLScene(slicer.mrmlScene)
    self.__volumeSelector.addEnabled = False
    
    inputFrameLayout.addRow(label, self.__volumeSelector)

    self.__volumeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onAnnotatedVolumeNodeChanged)
    self.__volumeSelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onMRMLSceneChanged)

    #
    # Annotation frame -- vocabulary-based description of what is
    # being annotated/marked up in this report
    #
    self.__annotationsFrame = ctk.ctkCollapsibleButton()
    self.__annotationsFrame.text = "Annotation"
    self.__annotationsFrame.collapsed = 0
    annotationsFrameLayout = qt.QFormLayout(self.__annotationsFrame)
    
    self.layout.addWidget(self.__annotationsFrame)

    self.__defaultColorNode = self.__logic.GetDefaultColorNode()

    self.__toolsColor = EditColor(self.__annotationsFrame,colorNode=self.__defaultColorNode)

    #
    # Markup frame -- summary of all the markup elements contained in the
    # report
    #
    self.__markupFrame = ctk.ctkCollapsibleButton()
    self.__markupFrame.text = "Markup"
    self.__markupFrame.collapsed = 0
    markupFrameLayout = qt.QFormLayout(self.__markupFrame)
    
    self.layout.addWidget(self.__markupFrame)

    # Add a flag to switch between different tree view models
    self.__useNewTreeView = 1

    # Add the tree widget
    if self.__useNewTreeView == 1:
      self.__markupTreeView = slicer.modulewidget.qMRMLReportingTreeView()
      self.__markupTreeView.sceneModelType = "DisplayableHierarchy"
    else:
      self.__markupTreeView = slicer.qMRMLTreeView()
      self.__markupTreeView.sceneModelType = "Displayable"
    self.__markupTreeView.setMRMLScene(self.__logic.GetMRMLScene())
        
    self.__markupSliceText = qt.QLabel()
    markupFrameLayout.addRow(self.__markupSliceText)
    markupFrameLayout.addRow(self.__markupTreeView)

    # Editor frame
    self.__editorFrame = ctk.ctkCollapsibleButton()
    self.__editorFrame.text = 'Segmentation'
    self.__editorFrame.collapsed = 0
    editorFrameLayout = qt.QFormLayout(self.__editorFrame)

    label = qt.QLabel('Segmentation volume: ')
    self.__segmentationSelector = slicer.qMRMLNodeComboBox()
    self.__segmentationSelector.nodeTypes = ['vtkMRMLScalarVolumeNode']
    self.__segmentationSelector.setMRMLScene(slicer.mrmlScene)
    self.__segmentationSelector.addEnabled = 1
    self.__segmentationSelector.noneEnabled = 1
    self.__segmentationSelector.removeEnabled = 0
    self.__segmentationSelector.showHidden = 0
    self.__segmentationSelector.showChildNodeTypes = 0
    self.__segmentationSelector.selectNodeUponCreation = 1
    self.__segmentationSelector.addAttribute('vtkMRMLScalarVolumeNode','LabelMap',1)

    editorFrameLayout.addRow(label, self.__segmentationSelector)

    editorWidgetParent = slicer.qMRMLWidget()
    editorWidgetParent.setLayout(qt.QVBoxLayout())
    editorWidgetParent.setMRMLScene(slicer.mrmlScene)
    self.__editorWidget = EditorWidget(parent=editorWidgetParent,showVolumesFrame=False)
    self.__editorWidget.setup()
    self.__editorWidget.toolsColor.frame.setVisible(False)
    editorFrameLayout.addRow(editorWidgetParent)

    markupFrameLayout.addRow(self.__editorFrame)

    self.__segmentationSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onSegmentationNodeChanged)
    self.__segmentationSelector.connect('mrmlSceneChanged(vtkMRMLScene*)', self.onMRMLSceneChanged)

    # IO frame
    self.__ioFrame = ctk.ctkCollapsibleButton()
    self.__ioFrame.text = 'Import/Export'
    self.__ioFrame.collapsed = 1
    ioFrameLayout = qt.QGridLayout(self.__ioFrame)

    self.layout.addWidget(self.__ioFrame)

    # Buttons to save/load report using AIM XML serialization
    label = qt.QLabel('Export folder')
    self.__exportFolderPicker = ctk.ctkDirectoryButton()
    exportButton = qt.QPushButton('Export')
    exportButton.connect('clicked()', self.onReportExport)
    ioFrameLayout.addWidget(label,0,0)
    ioFrameLayout.addWidget(self.__exportFolderPicker,0,1)
    ioFrameLayout.addWidget(exportButton,0,2)

    label = qt.QLabel('AIM file to import')
    self.__aimFilePicker = qt.QPushButton('N/A')
    self.__aimFilePicker.connect('clicked()',self.onSelectAIMFile)
    button = qt.QPushButton('Import')
    button.connect('clicked()', self.onReportImport)
    ioFrameLayout.addWidget(label,1,0)
    ioFrameLayout.addWidget(self.__aimFilePicker,1,1)
    ioFrameLayout.addWidget(button,1,2)
    self.__importAIMFile = None

    self.__reportSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.updateWidgets)
    self.__volumeSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.updateWidgets)
    self.updateWidgets()

    self.layout.addStretch(1)

    self.__editorParameterNode = self.editUtil.getParameterNode()

    self.__editorParameterNode.AddObserver(vtk.vtkCommand.ModifiedEvent, self.onEditorParameterNodeChanged)
Ejemplo n.º 4
0
# This module was tested on 3D Slicer version 4.3.1
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)
        self.moduleName = "AnglePlanes"
        self.i = 0
        self.logic = AnglePlanesLogic()
        self.planeControlsId = 0
        self.planeControlsDictionary = {}
        self.midPointFiducialDictionaryID = {}
        # self.logic.initializePlane()
        
        self.n_vector = numpy.matrix([[0], [0], [1], [1]])

        self.interactionNode = slicer.mrmlScene.GetNodeByID("vtkMRMLInteractionNodeSingleton")
        #Definition of the 2 planes

        # Collapsible button -- Scene Description
        self.loadCollapsibleButton = ctk.ctkCollapsibleButton()
        self.loadCollapsibleButton.text = "Scene"
        self.layout.addWidget(self.loadCollapsibleButton)

        # Layout within the laplace collapsible button
        self.loadFormLayout = qt.QFormLayout(self.loadCollapsibleButton)

        #--------------------------- List of Models --------------------------#

        treeView = slicer.qMRMLTreeView()
        treeView.setMRMLScene(slicer.app.mrmlScene())
        treeView.setSceneModelType('Displayable')
        treeView.sceneModel().setHorizontalHeaderLabels(["Models"])
        treeView.sortFilterProxyModel().nodeTypes = ['vtkMRMLModelNode']
        header = treeView.header()
        header.setResizeMode(0, qt.QHeaderView.Stretch)
        header.setVisible(True)
        self.loadFormLayout.addWidget(treeView)

        # numNodes = slicer.mrmlScene.GetNumberOfNodesByClass("vtkMRMLModelNode")
        # for i in range (3,numNodes):
        #     self.elements = slicer.mrmlScene.GetNthNodeByClass(i,"vtkMRMLModelNode" )
        #     print self.elements.GetName()

        # Add vertical spacer
        self.layout.addStretch(1)
        #------------------------ Compute Bounding Box ----------------------#
        buttonFrameBox = qt.QFrame(self.parent)
        buttonFrameBox.setLayout(qt.QHBoxLayout())
        self.loadFormLayout.addWidget(buttonFrameBox)

        self.computeBox = qt.QPushButton("Compute Bounding Box around all models")
        buttonFrameBox.layout().addWidget(self.computeBox)
        self.computeBox.connect('clicked()', self.onComputeBox)


        self.CollapsibleButton = ctk.ctkCollapsibleButton()
        self.CollapsibleButton.text = "Manage planes"
        self.layout.addWidget(self.CollapsibleButton)
        self.managePlanesFormLayout = qt.QFormLayout(self.CollapsibleButton)
        self.CollapsibleButton.checked = True

        # Add planes and manage landmark addition to each plane

        addNewPlaneLayout = qt.QHBoxLayout()
        addPlaneLabel = qt.QLabel('Add new plane')
        addPlaneButton = qt.QPushButton(qt.QIcon(":/Icons/MarkupsAddFiducial.png"), " ")
        addPlaneButton.setFixedSize(50,25)
        addPlaneButton.connect('clicked()', self.addNewPlane)
        addPlaneButton.setEnabled(True)
        addNewPlaneLayout.addWidget(addPlaneLabel)
        addNewPlaneLayout.addWidget(addPlaneButton)
        
        self.managePlanesFormLayout.addRow(addNewPlaneLayout)

        #        ----------------- Compute Mid Point -------------   
        self.midPointGroupBox = ctk.ctkCollapsibleButton()
        self.midPointGroupBox.setText('Define middle point between two landmarks') 
        self.midPointGroupBox.collapsed = True
        self.parent.layout().addWidget(self.midPointGroupBox)
        self.landmarkComboBox1MidPoint = qt.QComboBox()
        self.landmarkComboBox2MidPoint = qt.QComboBox()
        landmark1Layout = qt.QFormLayout()
        landmark1Layout.addRow('Landmark A: ', self.landmarkComboBox1MidPoint)
        landmark1Layout.addRow('Landmark B: ', self.landmarkComboBox2MidPoint)

        self.defineMiddlePointButton = qt.QPushButton(' Add middle point ')
        # self.midPointOnSurfaceCheckBox = qt.QCheckBox('On Surface')
        # self.midPointOnSurfaceCheckBox.setChecked(False)
        exportLayout_1 = qt.QFormLayout()
        # exportLayout_1.addRow(self.midPointOnSurfaceCheckBox, self.defineMiddlePointButton)
        exportLayout_1.addRow(self.defineMiddlePointButton)
        self.midPointLayout = qt.QVBoxLayout()
        self.midPointLayout.addLayout(landmark1Layout)
        self.midPointLayout.addLayout(exportLayout_1)
        self.midPointGroupBox.setLayout(self.midPointLayout)

        self.defineMiddlePointButton.connect('clicked()', self.onAddMidPoint)
        # self.landmarkComboBox1MidPoint.connect('currentIndexChanged(int)', self.onUpdateMidPoint)
        # self.landmarkComboBox2MidPoint.connect('currentIndexChanged(int)', self.onUpdateMidPoint)



        # -------- Calculate angles between planes ------------

        self.CollapsibleButtonPlane = ctk.ctkCollapsibleButton()
        self.CollapsibleButtonPlane.text = "Choose planes"
        self.layout.addWidget(self.CollapsibleButtonPlane)
        sampleFormLayoutPlane = qt.QFormLayout(self.CollapsibleButtonPlane)


        self.planeComboBox1 = qt.QComboBox()
        self.planeComboBox1.addItem("red")
        self.planeComboBox1.addItem("yellow")
        self.planeComboBox1.addItem("green")
        sampleFormLayoutPlane.addRow("Select plane 1: ", self.planeComboBox1)


        self.planeComboBox2 = qt.QComboBox()
        self.planeComboBox2.addItem("red")
        self.planeComboBox2.addItem("yellow")
        self.planeComboBox2.addItem("green")
        sampleFormLayoutPlane.addRow("Select plane 2: ", self.planeComboBox2)


        self.CollapsibleButton2 = ctk.ctkCollapsibleButton()
        self.CollapsibleButton2.text = "Results"
        self.layout.addWidget(self.CollapsibleButton2)
        sampleFormLayout2 = qt.QFormLayout(self.CollapsibleButton2)

        self.results = qt.QPushButton("Results")
        self.results.connect('clicked()', self.angleValue)
        sampleFormLayout2.addWidget(self.results)

        label_RL = qt.QLabel("R-L View")
        self.getAngle_RL = qt.QLabel("0")

        label_SI = qt.QLabel("S-I View")
        self.getAngle_SI = qt.QLabel("0")

        label_AP = qt.QLabel("A-P View")
        self.getAngle_AP = qt.QLabel("0")


        self.getAngle_RL_comp = qt.QLabel("0")
        self.getAngle_SI_comp = qt.QLabel("0")
        self.getAngle_AP_comp = qt.QLabel("0")


        tableResult = qt.QTableWidget(3, 3)
        tableResult.setColumnCount(3)
        tableResult.setHorizontalHeaderLabels([' View ', 'Angle', 'Complementary angle'])
        tableResult.setColumnWidth(0, 80)
        tableResult.setColumnWidth(1, 80)
        tableResult.setColumnWidth(2, 180)

        tableResult.setRowCount(1)
        tableResult.setCellWidget(0, 0, label_RL)
        tableResult.setCellWidget(0, 1, self.getAngle_RL)
        tableResult.setCellWidget(0, 2, self.getAngle_RL_comp)

        tableResult.setRowCount(2)
        tableResult.setCellWidget(1, 0, label_SI)
        tableResult.setCellWidget(1, 1, self.getAngle_SI)
        tableResult.setCellWidget(1, 2, self.getAngle_SI_comp)

        tableResult.setRowCount(3)
        tableResult.setCellWidget(2, 0, label_AP)
        tableResult.setCellWidget(2, 1, self.getAngle_AP)
        tableResult.setCellWidget(2, 2, self.getAngle_AP_comp)


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

        sampleFormLayout2.addWidget(tableResult)

        self.CollapsibleButton3 = ctk.ctkCollapsibleButton()
        self.CollapsibleButton3.text = "Save"
        self.layout.addWidget(self.CollapsibleButton3)
        sampleFormLayout3 = qt.QFormLayout(self.CollapsibleButton3)
        self.CollapsibleButton3.checked = False

        buttonFrame = qt.QFrame(self.parent)
        buttonFrame.setLayout(qt.QVBoxLayout())
        sampleFormLayout3.addWidget(buttonFrame)

        #-------------------------------- PLANES --------------------------------#
        save_plane = qt.QLabel("Save the planes you create as a txt file.")
        buttonFrame.layout().addWidget(save_plane)
        save = qt.QPushButton("Save plane")
        buttonFrame.layout().addWidget(save)

        # load_plane = qt.QLabel("Load the file with the plane you saved.")
        # buttonFrame.layout().addWidget(load_plane)
        read = qt.QPushButton("Load plane")
        buttonFrame.layout().addWidget(read)

        #-------------------------------- CONNECTIONS --------------------------------#
        self.planeComboBox1.connect('currentIndexChanged(QString)', self.valueComboBox)
        self.planeComboBox2.connect('currentIndexChanged(QString)', self.valueComboBox)

        save.connect('clicked(bool)', self.onSavePlanes)
        read.connect('clicked(bool)', self.onReadPlanes)
                                                                                                                
        slicer.mrmlScene.AddObserver(slicer.mrmlScene.EndCloseEvent, self.onCloseScene)


        self.pointLocatorDictionary = {}


        numNodes = slicer.mrmlScene.GetNumberOfNodesByClass("vtkMRMLModelNode")
        for i in range (3, numNodes):
            modelnode = slicer.mrmlScene.GetNthNodeByClass(i,"vtkMRMLModelNode" )
            self.addModelPointLocator(modelnode.GetName(), modelnode.GetPolyData())
        
        ModelAddedClass(self)
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)
        self.moduleName = "AnglePlanes"
        self.i = 0
        self.logic = AnglePlanesLogic()
        # self.logic.initializePlane()
        
        self.n_vector = numpy.matrix([[0], [0], [1], [1]])
        
        self.interactionNode = slicer.mrmlScene.GetNodeByID("vtkMRMLInteractionNodeSingleton")
        #Definition of the 2 planes

        # Collapsible button -- Scene Description
        self.loadCollapsibleButton = ctk.ctkCollapsibleButton()
        self.loadCollapsibleButton.text = "Scene"
        self.layout.addWidget(self.loadCollapsibleButton)

        # Layout within the laplace collapsible button
        self.loadFormLayout = qt.QFormLayout(self.loadCollapsibleButton)

        #--------------------------- List of Models --------------------------#

        treeView = slicer.qMRMLTreeView()
        treeView.setMRMLScene(slicer.app.mrmlScene())
        treeView.setSceneModelType('Displayable')
        treeView.sceneModel().setHorizontalHeaderLabels(["Models"])
        treeView.sortFilterProxyModel().nodeTypes = ['vtkMRMLModelNode']
        header = treeView.header()
        header.setResizeMode(0, qt.QHeaderView.Stretch)
        header.setVisible(True)
        self.loadFormLayout.addWidget(treeView)

        numNodes = slicer.mrmlScene.GetNumberOfNodesByClass("vtkMRMLModelNode")
        for i in range (3,numNodes):
            self.elements = slicer.mrmlScene.GetNthNodeByClass(i,"vtkMRMLModelNode" )
            print self.elements.GetName()

        # Add vertical spacer
        self.layout.addStretch(1)
        #------------------------ Compute Bounding Box ----------------------#
        buttonFrameBox = qt.QFrame(self.parent)
        buttonFrameBox.setLayout(qt.QHBoxLayout())
        self.loadFormLayout.addWidget(buttonFrameBox)

        self.computeBox = qt.QPushButton("Compute Bounding Box around all models")
        buttonFrameBox.layout().addWidget(self.computeBox)
        self.computeBox.connect('clicked()', self.onComputeBox)


        self.CollapsibleButton = ctk.ctkCollapsibleButton()
        self.CollapsibleButton.text = "Place Landmarks to define plane"
        self.layout.addWidget(self.CollapsibleButton)
        sampleFormLayout = qt.QFormLayout(self.CollapsibleButton)
        self.CollapsibleButton.checked = False

        # Collapsible button

        landmarkFrame = qt.QFrame()
        landmarkFrame.setLayout(qt.QHBoxLayout())
        landmarkLabel = qt.QLabel('Add Landmarks ')
        self.addLandMark = qt.QPushButton(qt.QIcon(":/Icons/MarkupsAddFiducial.png"), " ")
        self.addLandMark.setFixedSize(50,25)
        self.addLandMark.connect('clicked()', self.addLandMarkClicked)
        self.addLandMark.setEnabled(True)
        landmarkFrame.layout().addWidget(landmarkLabel)
        landmarkFrame.layout().addWidget(self.addLandMark)

        # MIDPOINT PART

        # labelLandmark = qt.QLabel('Choose 3 Landmarks to define the plane: ')
        #
        # label1 = qt.QLabel('Landmark 1: ')
        # self.Landmark1ComboBox = qt.QComboBox()
        # self.Landmark1ComboBox.addItem("List of fiducials")
        # landmark1Layout = qt.QHBoxLayout()
        # landmark1Layout.addWidget(label1)
        # landmark1Layout.addWidget(self.Landmark1ComboBox)
        #
        # label2 = qt.QLabel('Landmark 2: ')
        # self.Landmark2ComboBox = qt.QComboBox()
        # self.Landmark2ComboBox.addItem("List of fiducials")
        # landmark2Layout = qt.QHBoxLayout()
        # landmark2Layout.addWidget(label2)
        # landmark2Layout.addWidget(self.Landmark2ComboBox)

        labelLandmark = qt.QLabel('Choose 3 Landmarks to define the plane: ')

        label1 = qt.QLabel('Landmark 1: ')
        self.Landmark1ComboBox = qt.QComboBox()
        self.Landmark1ComboBox.addItem("List of fiducials")
        landmark1Layout = qt.QHBoxLayout()
        landmark1Layout.addWidget(label1)
        landmark1Layout.addWidget(self.Landmark1ComboBox)


        label2 = qt.QLabel('Landmark 2: ')
        self.Landmark2ComboBox = qt.QComboBox()
        self.Landmark2ComboBox.addItem("List of fiducials")
        landmark2Layout = qt.QHBoxLayout()
        landmark2Layout.addWidget(label2)
        landmark2Layout.addWidget(self.Landmark2ComboBox)

        label3 = qt.QLabel('Landmark 3: ')
        self.Landmark3ComboBox = qt.QComboBox()
        self.Landmark3ComboBox.addItem("List of fiducials")
        landmark3Layout = qt.QHBoxLayout()
        landmark3Layout.addWidget(label3)
        landmark3Layout.addWidget(self.Landmark3ComboBox)

        self.placePlaneButton = qt.QPushButton("Define and Place Planes")
        self.placePlaneButton.connect('clicked()', self.onValueChanged)


        self.slider = ctk.ctkSliderWidget()
        self.slider.singleStep = 0.1
        self.slider.minimum = 0.1
        self.slider.maximum = 100
        self.slider.value = 1.0
        self.slider.toolTip = "Set the size of your plane."

        self.slideOpacity = ctk.ctkSliderWidget()
        self.slideOpacity.singleStep = 0.1
        self.slideOpacity.minimum = 0.1
        self.slideOpacity.maximum = 1
        self.slideOpacity.value = 1.0
        self.slider.toolTip = "Set the opacity of your plane."

        sampleFormLayout.addRow(landmarkFrame)
        sampleFormLayout.addRow(labelLandmark)
        sampleFormLayout.addRow(landmark1Layout)
        sampleFormLayout.addRow(landmark2Layout)
        sampleFormLayout.addRow(landmark3Layout)
        sampleFormLayout.addRow(self.placePlaneButton)
        sampleFormLayout.addRow("Size of your plane", self.slider)
        sampleFormLayout.addRow("Opacity of your plane", self.slideOpacity)


        self.CollapsibleButtonPlane = ctk.ctkCollapsibleButton()
        self.CollapsibleButtonPlane.text = "Choose planes"
        self.layout.addWidget(self.CollapsibleButtonPlane)
        sampleFormLayoutPlane = qt.QFormLayout(self.CollapsibleButtonPlane)


        self.planeComboBox1 = qt.QComboBox()
        self.planeComboBox1.addItem("red")
        self.planeComboBox1.addItem("yellow")
        self.planeComboBox1.addItem("green")
        self.planeComboBox1.addItem("Landmarks")
        sampleFormLayoutPlane.addRow("Select plane 1: ", self.planeComboBox1)


        self.planeComboBox2 = qt.QComboBox()
        self.planeComboBox2.addItem("red")
        self.planeComboBox2.addItem("yellow")
        self.planeComboBox2.addItem("green")
        self.planeComboBox2.addItem("Landmarks")
        sampleFormLayoutPlane.addRow("Select plane 2: ", self.planeComboBox2)


        self.CollapsibleButton2 = ctk.ctkCollapsibleButton()
        self.CollapsibleButton2.text = "Results"
        self.layout.addWidget(self.CollapsibleButton2)
        sampleFormLayout2 = qt.QFormLayout(self.CollapsibleButton2)

        self.results = qt.QPushButton("Results")
        self.results.connect('clicked()', self.angleValue)
        sampleFormLayout2.addWidget(self.results)

        label_RL = qt.QLabel("R-L View")
        self.getAngle_RL = qt.QLabel("0")

        label_SI = qt.QLabel("S-I View")
        self.getAngle_SI = qt.QLabel("0")

        label_AP = qt.QLabel("A-P View")
        self.getAngle_AP = qt.QLabel("0")


        self.getAngle_RL_comp = qt.QLabel("0")
        self.getAngle_SI_comp = qt.QLabel("0")
        self.getAngle_AP_comp = qt.QLabel("0")


        tableResult = qt.QTableWidget(3, 3)
        tableResult.setColumnCount(3)
        tableResult.setHorizontalHeaderLabels([' View ', 'Angle', 'Complementary angle'])
        tableResult.setColumnWidth(0, 80)
        tableResult.setColumnWidth(1, 80)
        tableResult.setColumnWidth(2, 180)

        tableResult.setRowCount(1)
        tableResult.setCellWidget(0, 0, label_RL)
        tableResult.setCellWidget(0, 1, self.getAngle_RL)
        tableResult.setCellWidget(0, 2, self.getAngle_RL_comp)

        tableResult.setRowCount(2)
        tableResult.setCellWidget(1, 0, label_SI)
        tableResult.setCellWidget(1, 1, self.getAngle_SI)
        tableResult.setCellWidget(1, 2, self.getAngle_SI_comp)

        tableResult.setRowCount(3)
        tableResult.setCellWidget(2, 0, label_AP)
        tableResult.setCellWidget(2, 1, self.getAngle_AP)
        tableResult.setCellWidget(2, 2, self.getAngle_AP_comp)


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

        sampleFormLayout2.addWidget(tableResult)

        self.CollapsibleButton3 = ctk.ctkCollapsibleButton()
        self.CollapsibleButton3.text = "Save"
        self.layout.addWidget(self.CollapsibleButton3)
        sampleFormLayout3 = qt.QFormLayout(self.CollapsibleButton3)
        self.CollapsibleButton3.checked = False

        buttonFrame = qt.QFrame(self.parent)
        buttonFrame.setLayout(qt.QVBoxLayout())
        sampleFormLayout3.addWidget(buttonFrame)

        #-------------------------------- PLANES --------------------------------#
        save_plane = qt.QLabel("Save the planes you create as a txt file.")
        buttonFrame.layout().addWidget(save_plane)
        save = qt.QPushButton("Save plane")
        buttonFrame.layout().addWidget(save)

        # load_plane = qt.QLabel("Load the file with the plane you saved.")
        # buttonFrame.layout().addWidget(load_plane)
        read = qt.QPushButton("Load plane")
        buttonFrame.layout().addWidget(read)

        #-------------------------------- CONNECTIONS --------------------------------#
        self.planeComboBox1.connect('currentIndexChanged(QString)', self.valueComboBox)
        self.planeComboBox2.connect('currentIndexChanged(QString)', self.valueComboBox)


        self.slider.connect('valueChanged(double)', self.onValueChanged)
        self.slideOpacity.connect('valueChanged(double)', self.onValueChanged)

        save.connect('clicked(bool)', self.logic.savePlane)
        read.connect('clicked(bool)', self.logic.readPlane)
                                                                                                                
        slicer.mrmlScene.AddObserver(slicer.mrmlScene.EndCloseEvent, self.onCloseScene)
Ejemplo n.º 7
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)
        self.moduleName = "AnglePlanes"
        self.i = 0
        self.logic = AnglePlanesLogic()
        self.planeControlsId = 0
        self.planeControlsDictionary = {}
        self.midPointFiducialDictionaryID = {}
        # self.logic.initializePlane()

        self.n_vector = numpy.matrix([[0], [0], [1], [1]])

        self.interactionNode = slicer.mrmlScene.GetNodeByID(
            "vtkMRMLInteractionNodeSingleton")
        #Definition of the 2 planes

        # Collapsible button -- Scene Description
        self.loadCollapsibleButton = ctk.ctkCollapsibleButton()
        self.loadCollapsibleButton.text = "Scene"
        self.layout.addWidget(self.loadCollapsibleButton)

        # Layout within the laplace collapsible button
        self.loadFormLayout = qt.QFormLayout(self.loadCollapsibleButton)

        #--------------------------- List of Models --------------------------#

        treeView = slicer.qMRMLTreeView()
        treeView.setMRMLScene(slicer.app.mrmlScene())
        treeView.setSceneModelType('Displayable')
        treeView.sceneModel().setHorizontalHeaderLabels(["Models"])
        treeView.sortFilterProxyModel().nodeTypes = ['vtkMRMLModelNode']
        header = treeView.header()
        header.setResizeMode(0, qt.QHeaderView.Stretch)
        header.setVisible(True)
        self.loadFormLayout.addWidget(treeView)

        # numNodes = slicer.mrmlScene.GetNumberOfNodesByClass("vtkMRMLModelNode")
        # for i in range (3,numNodes):
        #     self.elements = slicer.mrmlScene.GetNthNodeByClass(i,"vtkMRMLModelNode" )
        #     print self.elements.GetName()

        # Add vertical spacer
        self.layout.addStretch(1)
        #------------------------ Compute Bounding Box ----------------------#
        buttonFrameBox = qt.QFrame(self.parent)
        buttonFrameBox.setLayout(qt.QHBoxLayout())
        self.loadFormLayout.addWidget(buttonFrameBox)

        self.computeBox = qt.QPushButton(
            "Compute Bounding Box around all models")
        buttonFrameBox.layout().addWidget(self.computeBox)
        self.computeBox.connect('clicked()', self.onComputeBox)

        self.CollapsibleButton = ctk.ctkCollapsibleButton()
        self.CollapsibleButton.text = "Manage planes"
        self.layout.addWidget(self.CollapsibleButton)
        self.managePlanesFormLayout = qt.QFormLayout(self.CollapsibleButton)
        self.CollapsibleButton.checked = True

        # Add planes and manage landmark addition to each plane

        addNewPlaneLayout = qt.QHBoxLayout()
        addPlaneLabel = qt.QLabel('Add new plane')
        addPlaneButton = qt.QPushButton(
            qt.QIcon(":/Icons/MarkupsAddFiducial.png"), " ")
        addPlaneButton.setFixedSize(50, 25)
        addPlaneButton.connect('clicked()', self.addNewPlane)
        addPlaneButton.setEnabled(True)
        addNewPlaneLayout.addWidget(addPlaneLabel)
        addNewPlaneLayout.addWidget(addPlaneButton)

        self.managePlanesFormLayout.addRow(addNewPlaneLayout)

        #        ----------------- Compute Mid Point -------------
        self.midPointGroupBox = ctk.ctkCollapsibleButton()
        self.midPointGroupBox.setText(
            'Define middle point between two landmarks')
        self.midPointGroupBox.collapsed = True
        self.parent.layout().addWidget(self.midPointGroupBox)
        self.landmarkComboBox1MidPoint = qt.QComboBox()
        self.landmarkComboBox2MidPoint = qt.QComboBox()
        landmark1Layout = qt.QFormLayout()
        landmark1Layout.addRow('Landmark A: ', self.landmarkComboBox1MidPoint)
        landmark1Layout.addRow('Landmark B: ', self.landmarkComboBox2MidPoint)

        self.defineMiddlePointButton = qt.QPushButton(' Add middle point ')
        # self.midPointOnSurfaceCheckBox = qt.QCheckBox('On Surface')
        # self.midPointOnSurfaceCheckBox.setChecked(False)
        exportLayout_1 = qt.QFormLayout()
        # exportLayout_1.addRow(self.midPointOnSurfaceCheckBox, self.defineMiddlePointButton)
        exportLayout_1.addRow(self.defineMiddlePointButton)
        self.midPointLayout = qt.QVBoxLayout()
        self.midPointLayout.addLayout(landmark1Layout)
        self.midPointLayout.addLayout(exportLayout_1)
        self.midPointGroupBox.setLayout(self.midPointLayout)

        self.defineMiddlePointButton.connect('clicked()', self.onAddMidPoint)
        # self.landmarkComboBox1MidPoint.connect('currentIndexChanged(int)', self.onUpdateMidPoint)
        # self.landmarkComboBox2MidPoint.connect('currentIndexChanged(int)', self.onUpdateMidPoint)

        # -------- Calculate angles between planes ------------

        self.CollapsibleButtonPlane = ctk.ctkCollapsibleButton()
        self.CollapsibleButtonPlane.text = "Choose planes"
        self.layout.addWidget(self.CollapsibleButtonPlane)
        sampleFormLayoutPlane = qt.QFormLayout(self.CollapsibleButtonPlane)

        self.planeComboBox1 = qt.QComboBox()
        self.planeComboBox1.addItem("red")
        self.planeComboBox1.addItem("yellow")
        self.planeComboBox1.addItem("green")
        sampleFormLayoutPlane.addRow("Select plane 1: ", self.planeComboBox1)

        self.planeComboBox2 = qt.QComboBox()
        self.planeComboBox2.addItem("red")
        self.planeComboBox2.addItem("yellow")
        self.planeComboBox2.addItem("green")
        sampleFormLayoutPlane.addRow("Select plane 2: ", self.planeComboBox2)

        self.CollapsibleButton2 = ctk.ctkCollapsibleButton()
        self.CollapsibleButton2.text = "Results"
        self.layout.addWidget(self.CollapsibleButton2)
        sampleFormLayout2 = qt.QFormLayout(self.CollapsibleButton2)

        self.results = qt.QPushButton("Results")
        self.results.connect('clicked()', self.angleValue)
        sampleFormLayout2.addWidget(self.results)

        label_RL = qt.QLabel("R-L View")
        self.getAngle_RL = qt.QLabel("0")

        label_SI = qt.QLabel("S-I View")
        self.getAngle_SI = qt.QLabel("0")

        label_AP = qt.QLabel("A-P View")
        self.getAngle_AP = qt.QLabel("0")

        self.getAngle_RL_comp = qt.QLabel("0")
        self.getAngle_SI_comp = qt.QLabel("0")
        self.getAngle_AP_comp = qt.QLabel("0")

        tableResult = qt.QTableWidget(3, 3)
        tableResult.setColumnCount(3)
        tableResult.setHorizontalHeaderLabels(
            [' View ', 'Angle', 'Complementary angle'])
        tableResult.setColumnWidth(0, 80)
        tableResult.setColumnWidth(1, 80)
        tableResult.setColumnWidth(2, 180)

        tableResult.setRowCount(1)
        tableResult.setCellWidget(0, 0, label_RL)
        tableResult.setCellWidget(0, 1, self.getAngle_RL)
        tableResult.setCellWidget(0, 2, self.getAngle_RL_comp)

        tableResult.setRowCount(2)
        tableResult.setCellWidget(1, 0, label_SI)
        tableResult.setCellWidget(1, 1, self.getAngle_SI)
        tableResult.setCellWidget(1, 2, self.getAngle_SI_comp)

        tableResult.setRowCount(3)
        tableResult.setCellWidget(2, 0, label_AP)
        tableResult.setCellWidget(2, 1, self.getAngle_AP)
        tableResult.setCellWidget(2, 2, self.getAngle_AP_comp)

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

        sampleFormLayout2.addWidget(tableResult)

        self.CollapsibleButton3 = ctk.ctkCollapsibleButton()
        self.CollapsibleButton3.text = "Save"
        self.layout.addWidget(self.CollapsibleButton3)
        sampleFormLayout3 = qt.QFormLayout(self.CollapsibleButton3)
        self.CollapsibleButton3.checked = False

        buttonFrame = qt.QFrame(self.parent)
        buttonFrame.setLayout(qt.QVBoxLayout())
        sampleFormLayout3.addWidget(buttonFrame)

        #-------------------------------- PLANES --------------------------------#
        save_plane = qt.QLabel("Save the planes you create as a txt file.")
        buttonFrame.layout().addWidget(save_plane)
        save = qt.QPushButton("Save plane")
        buttonFrame.layout().addWidget(save)

        # load_plane = qt.QLabel("Load the file with the plane you saved.")
        # buttonFrame.layout().addWidget(load_plane)
        read = qt.QPushButton("Load plane")
        buttonFrame.layout().addWidget(read)

        #-------------------------------- CONNECTIONS --------------------------------#
        self.planeComboBox1.connect('currentIndexChanged(QString)',
                                    self.valueComboBox)
        self.planeComboBox2.connect('currentIndexChanged(QString)',
                                    self.valueComboBox)

        save.connect('clicked(bool)', self.onSavePlanes)
        read.connect('clicked(bool)', self.onReadPlanes)

        slicer.mrmlScene.AddObserver(slicer.mrmlScene.EndCloseEvent,
                                     self.onCloseScene)

        self.pointLocatorDictionary = {}

        numNodes = slicer.mrmlScene.GetNumberOfNodesByClass("vtkMRMLModelNode")
        for i in range(3, numNodes):
            modelnode = slicer.mrmlScene.GetNthNodeByClass(
                i, "vtkMRMLModelNode")
            self.addModelPointLocator(modelnode.GetName(),
                                      modelnode.GetPolyData())

        ModelAddedClass(self)