Пример #1
0
    def onCreatePresetPressed(self):
        if self.registrationPresetSelector.currentIndex != self.newPresetIndex:
            return

        self.newPresetBox = qt.QDialog()
        self.customPresetLayout = qt.QVBoxLayout()

        self.addParameterFile()

        addPresetButton = qt.QPushButton("Add more presets...")
        addPresetButton.connect("clicked(bool)", self.addParameterFile)
        self.customPresetLayout.addWidget(addPresetButton)
        self.newPresetBox.setLayout(self.customPresetLayout)

        # Add fields to specify descriptions, etc... for that preset (to be included in the XML file)

        groupBox = qt.QGroupBox()
        formLayout = qt.QFormLayout()

        self.contentBox = qt.QLineEdit()
        formLayout.addRow("Content: ", self.contentBox)
        self.descriptionBox = qt.QLineEdit()
        formLayout.addRow("Description: ", self.descriptionBox)
        self.idBox = qt.QLineEdit()
        formLayout.addRow("Id: ", self.idBox)
        self.modalityBox = qt.QLineEdit()
        formLayout.addRow("Modality: ", self.modalityBox)
        self.publicationsBox = qt.QPlainTextEdit()
        formLayout.addRow("Publications: ", self.publicationsBox)

        groupBox.setLayout(formLayout)
        self.customPresetLayout.addWidget(groupBox)

        # Add Ok/Cancel buttons and connect them to the main dialog
        buttonBox = qt.QDialogButtonBox()
        buttonBox.setStandardButtons(qt.QDialogButtonBox.Ok
                                     | qt.QDialogButtonBox.Cancel)
        buttonBox.setCenterButtons(True)
        buttonBox.connect("accepted()", self.newPresetBox.accept)
        buttonBox.connect("rejected()", self.newPresetBox.reject)

        self.customPresetLayout.addWidget(buttonBox)

        response = self.newPresetBox.exec_()

        if response:
            self.createPreset()
Пример #2
0
 def setup(self):
   ScriptedLoadableModuleWidget.setup(self)
   
   self.logic = EAMapReaderLogic()
   self.logic.logCallback = self.addLog
   self.logic.progressCallback = self.updateProgress
   self.loadingInProgress = False
   
   # Instantiate and connect widgets ...
   self.buttonVelocity = qt.QPushButton("Ensite Velocity / Precision")
   self.buttonVelocity.toolTip = "Import Ensite map."
   self.buttonVelocity.enabled = True
   self.layout.addWidget(self.buttonVelocity)
   
   self.buttonCarto = qt.QPushButton("CARTO 3")
   self.buttonCarto.toolTip = "Import CARTO 3 map."
   self.buttonCarto.enabled = True
   self.layout.addWidget(self.buttonCarto)
   
   self.buttonRhythmia = qt.QPushButton("RHYTHMIA")
   self.buttonRhythmia.toolTip = "Import RHYTHMIA Map."
   self.buttonRhythmia.enabled = True
   self.layout.addWidget(self.buttonRhythmia)
   
   self.statusLabel = qt.QPlainTextEdit()
   self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
   self.statusLabel.setCenterOnScroll(True)
   self.layout.addWidget(self.statusLabel)
   
   self.progressBar=qt.QProgressBar()
   self.progressBar.setRange(0, 100) 
   self.progressBar.setValue(0)
   self.layout.addWidget(self.progressBar)
   
   # connections
   self.buttonVelocity.connect('clicked(bool)', self.onButtonVelocity)
   self.buttonCarto.connect('clicked(bool)', self.onButtonCarto)
   self.buttonRhythmia.connect('clicked(bool)', self.onButtonRhythmia)
Пример #3
0
  def setup(self):
    ScriptedLoadableModuleWidget.setup(self)

    self.logic = ElastixLogic()
    self.logic.logCallback = self.addLog
    self.registrationInProgress = False

    # Instantiate and connect widgets ...

    # Parameter sets
    defaultinputParametersCollapsibleButton = ctk.ctkCollapsibleButton()
    defaultinputParametersCollapsibleButton.text = "Parameter set"
    defaultinputParametersCollapsibleButton.collapsed = True
    self.layout.addWidget(defaultinputParametersCollapsibleButton)
    defaultParametersLayout = qt.QFormLayout(defaultinputParametersCollapsibleButton)

    self.parameterNodeSelector = slicer.qMRMLNodeComboBox()
    self.parameterNodeSelector.nodeTypes = ["vtkMRMLScriptedModuleNode"]
    self.parameterNodeSelector.addAttribute( "vtkMRMLScriptedModuleNode", "ModuleName", "Elastix" )
    self.parameterNodeSelector.selectNodeUponCreation = True
    self.parameterNodeSelector.addEnabled = True
    self.parameterNodeSelector.renameEnabled = True
    self.parameterNodeSelector.removeEnabled = True
    self.parameterNodeSelector.noneEnabled = False
    self.parameterNodeSelector.showHidden = True
    self.parameterNodeSelector.showChildNodeTypes = False
    self.parameterNodeSelector.baseName = "General Registration (Elastix)"
    self.parameterNodeSelector.setMRMLScene( slicer.mrmlScene )
    self.parameterNodeSelector.setToolTip( "Pick parameter set" )
    defaultParametersLayout.addRow("Parameter set: ", self.parameterNodeSelector)

    #
    # Inputs
    #
    inputParametersCollapsibleButton = ctk.ctkCollapsibleButton()
    inputParametersCollapsibleButton.text = "Inputs"
    self.layout.addWidget(inputParametersCollapsibleButton)

    # Layout within the dummy collapsible button
    inputParametersFormLayout = qt.QFormLayout(inputParametersCollapsibleButton)

    #
    # fixed volume selector
    #
    self.fixedVolumeSelector = slicer.qMRMLNodeComboBox()
    self.fixedVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.fixedVolumeSelector.selectNodeUponCreation = True
    self.fixedVolumeSelector.addEnabled = False
    self.fixedVolumeSelector.removeEnabled = False
    self.fixedVolumeSelector.noneEnabled = False
    self.fixedVolumeSelector.showHidden = False
    self.fixedVolumeSelector.showChildNodeTypes = False
    self.fixedVolumeSelector.setMRMLScene( slicer.mrmlScene )
    self.fixedVolumeSelector.setToolTip( "The moving volume will be transformed into this image space." )
    inputParametersFormLayout.addRow("Fixed volume: ", self.fixedVolumeSelector)

    #
    # moving volume selector
    #
    self.movingVolumeSelector = slicer.qMRMLNodeComboBox()
    self.movingVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.movingVolumeSelector.selectNodeUponCreation = True
    self.movingVolumeSelector.addEnabled = False
    self.movingVolumeSelector.removeEnabled = False
    self.movingVolumeSelector.noneEnabled = False
    self.movingVolumeSelector.showHidden = False
    self.movingVolumeSelector.showChildNodeTypes = False
    self.movingVolumeSelector.setMRMLScene( slicer.mrmlScene )
    self.movingVolumeSelector.setToolTip( "This volume will be transformed into the fixed image space" )
    inputParametersFormLayout.addRow("Moving volume: ", self.movingVolumeSelector)

    self.registrationPresetSelector = qt.QComboBox()
    for preset in self.logic.getRegistrationPresets():
      self.registrationPresetSelector.addItem("{0} ({1})".format(preset[RegistrationPresets_Modality], preset[RegistrationPresets_Content]))
    inputParametersFormLayout.addRow("Preset: ", self.registrationPresetSelector)

    #
    # Outputs
    #
    maskingParametersCollapsibleButton = ctk.ctkCollapsibleButton()
    maskingParametersCollapsibleButton.text = "Masking"
    maskingParametersCollapsibleButton.collapsed = True
    self.layout.addWidget(maskingParametersCollapsibleButton)

    # Layout within the dummy collapsible button
    maskingParametersFormLayout = qt.QFormLayout(maskingParametersCollapsibleButton)

    #
    # fixed volume mask selector
    #
    self.fixedVolumeMaskSelector = slicer.qMRMLNodeComboBox()
    self.fixedVolumeMaskSelector.nodeTypes = ["vtkMRMLLabelMapVolumeNode"]
    self.fixedVolumeMaskSelector.addEnabled = False
    self.fixedVolumeMaskSelector.removeEnabled = False
    self.fixedVolumeMaskSelector.noneEnabled = True
    self.fixedVolumeMaskSelector.showHidden = False
    self.fixedVolumeMaskSelector.showChildNodeTypes = False
    self.fixedVolumeMaskSelector.setMRMLScene( slicer.mrmlScene )
    self.fixedVolumeMaskSelector.setToolTip("Areas of the fixed volume where mask label is 0 will be ignored in the registration.")
    maskingParametersFormLayout.addRow("Fixed volume mask: ", self.fixedVolumeMaskSelector)

    #
    # moving volume mask selector
    #
    self.movingVolumeMaskSelector = slicer.qMRMLNodeComboBox()
    self.movingVolumeMaskSelector.nodeTypes = ["vtkMRMLLabelMapVolumeNode"]
    self.movingVolumeMaskSelector.selectNodeUponCreation = True
    self.movingVolumeMaskSelector.addEnabled = False
    self.movingVolumeMaskSelector.removeEnabled = False
    self.movingVolumeMaskSelector.noneEnabled = True
    self.movingVolumeMaskSelector.showHidden = False
    self.movingVolumeMaskSelector.showChildNodeTypes = False
    self.movingVolumeMaskSelector.setMRMLScene( slicer.mrmlScene )
    self.movingVolumeMaskSelector.setToolTip("Areas of the moving volume where mask label is 0 will be ignored in the registration")
    maskingParametersFormLayout.addRow("Moving volume mask: ", self.movingVolumeMaskSelector)

    #
    # Outputs
    #
    outputParametersCollapsibleButton = ctk.ctkCollapsibleButton()
    outputParametersCollapsibleButton.text = "Outputs"
    self.layout.addWidget(outputParametersCollapsibleButton)

    # Layout within the dummy collapsible button
    outputParametersFormLayout = qt.QFormLayout(outputParametersCollapsibleButton)

    #
    # output volume selector
    #
    self.outputVolumeSelector = slicer.qMRMLNodeComboBox()
    self.outputVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.outputVolumeSelector.selectNodeUponCreation = True
    self.outputVolumeSelector.addEnabled = True
    self.outputVolumeSelector.renameEnabled = True
    self.outputVolumeSelector.removeEnabled = True
    self.outputVolumeSelector.noneEnabled = True
    self.outputVolumeSelector.showHidden = False
    self.outputVolumeSelector.showChildNodeTypes = False
    self.outputVolumeSelector.setMRMLScene( slicer.mrmlScene )
    self.outputVolumeSelector.setToolTip( "(optional) The moving image warped to the fixed image space. NOTE: You must set at least one output object (transform and/or output volume)" )
    outputParametersFormLayout.addRow("Output volume: ", self.outputVolumeSelector)

    #
    # output transform selector
    #
    self.outputTransformSelector = slicer.qMRMLNodeComboBox()
    self.outputTransformSelector.nodeTypes = ["vtkMRMLTransformNode"]
    self.outputTransformSelector.selectNodeUponCreation = True
    self.outputTransformSelector.addEnabled = True
    self.outputTransformSelector.renameEnabled = True
    self.outputTransformSelector.removeEnabled = True
    self.outputTransformSelector.noneEnabled = True
    self.outputTransformSelector.showHidden = False
    self.outputTransformSelector.showChildNodeTypes = False
    self.outputTransformSelector.setMRMLScene( slicer.mrmlScene )
    self.outputTransformSelector.setToolTip( "(optional) Computed displacement field that transform nodes from moving volume space to fixed volume space. NOTE: You must set at least one output object (transform and/or output volume)." )
    outputParametersFormLayout.addRow("Output transform: ", self.outputTransformSelector)

    #
    # Advanced area
    #
    self.advancedCollapsibleButton = ctk.ctkCollapsibleButton()
    self.advancedCollapsibleButton.text = "Advanced"
    self.advancedCollapsibleButton.collapsed = True
    self.layout.addWidget(self.advancedCollapsibleButton)
    advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton)

    self.showDetailedLogDuringExecutionCheckBox = qt.QCheckBox(" ")
    self.showDetailedLogDuringExecutionCheckBox.checked = False
    self.showDetailedLogDuringExecutionCheckBox.setToolTip("Show detailed log during registration.")
    advancedFormLayout.addRow("Show detailed log during registration:", self.showDetailedLogDuringExecutionCheckBox)

    self.keepTemporaryFilesCheckBox = qt.QCheckBox(" ")
    self.keepTemporaryFilesCheckBox.checked = False
    self.keepTemporaryFilesCheckBox.setToolTip("Keep temporary files (inputs, computed outputs, logs) after the registration is completed.")

    self.showTemporaryFilesFolderButton = qt.QPushButton("Show temp folder")
    self.showTemporaryFilesFolderButton.toolTip = "Open the folder where temporary files are stored."
    self.showTemporaryFilesFolderButton.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred)

    hbox = qt.QHBoxLayout()
    hbox.addWidget(self.keepTemporaryFilesCheckBox)
    hbox.addWidget(self.showTemporaryFilesFolderButton)
    advancedFormLayout.addRow("Keep temporary files:", hbox)

    self.showRegistrationParametersDatabaseFolderButton = qt.QPushButton("Show database folder")
    self.showRegistrationParametersDatabaseFolderButton.toolTip = "Open the folder where temporary files are stored."
    self.showRegistrationParametersDatabaseFolderButton.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred)
    advancedFormLayout.addRow("Registration presets:", self.showRegistrationParametersDatabaseFolderButton)

    customElastixBinDir = self.logic.getCustomElastixBinDir()
    self.customElastixBinDirSelector = ctk.ctkPathLineEdit()
    self.customElastixBinDirSelector.filters = ctk.ctkPathLineEdit.Dirs
    self.customElastixBinDirSelector.setCurrentPath(customElastixBinDir)
    self.customElastixBinDirSelector.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred)
    self.customElastixBinDirSelector.setToolTip("Set bin directory of an Elastix installation (where elastix executable is located). "
      "If value is empty then default elastix (bundled with SlicerElastix extension) will be used.")
    advancedFormLayout.addRow("Custom Elastix toolbox location:", self.customElastixBinDirSelector)

    #
    # Apply Button
    #
    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.toolTip = "Run the algorithm."
    self.applyButton.enabled = False
    self.layout.addWidget(self.applyButton)

    self.statusLabel = qt.QPlainTextEdit()
    self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
    self.statusLabel.setCenterOnScroll(True)
    self.layout.addWidget(self.statusLabel)

    # connections
    self.applyButton.connect('clicked(bool)', self.onApplyButton)
    self.showTemporaryFilesFolderButton.connect('clicked(bool)', self.onShowTemporaryFilesFolder)
    self.showRegistrationParametersDatabaseFolderButton.connect('clicked(bool)', self.onShowRegistrationParametersDatabaseFolder)
    self.fixedVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.movingVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.outputVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    self.outputTransformSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect)
    # Immediately update deleteTemporaryFiles in the logic to make it possible to decide to
    # keep the temporary file while the registration is running
    self.keepTemporaryFilesCheckBox.connect("toggled(bool)", self.onKeepTemporaryFilesToggled)

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

    # Refresh Apply button state
    self.onSelect()
Пример #4
0
  def setup(self):
    ScriptedLoadableModuleWidget.setup(self)

    self.logic = SegmentMesherLogic()
    self.logic.logCallback = self.addLog
    self.modelGenerationInProgress = False

    # Instantiate and connect widgets ...

    # Parameter sets
    defaultinputParametersCollapsibleButton = ctk.ctkCollapsibleButton()
    defaultinputParametersCollapsibleButton.text = "Parameter set"
    defaultinputParametersCollapsibleButton.collapsed = True
    self.layout.addWidget(defaultinputParametersCollapsibleButton)
    defaultParametersLayout = qt.QFormLayout(defaultinputParametersCollapsibleButton)

    self.parameterNodeSelector = slicer.qMRMLNodeComboBox()
    self.parameterNodeSelector.nodeTypes = ["vtkMRMLScriptedModuleNode"]
    self.parameterNodeSelector.addAttribute( "vtkMRMLScriptedModuleNode", "ModuleName", "SegmentMesher" )
    self.parameterNodeSelector.selectNodeUponCreation = True
    self.parameterNodeSelector.addEnabled = True
    self.parameterNodeSelector.renameEnabled = True
    self.parameterNodeSelector.removeEnabled = True
    self.parameterNodeSelector.noneEnabled = False
    self.parameterNodeSelector.showHidden = True
    self.parameterNodeSelector.showChildNodeTypes = False
    self.parameterNodeSelector.baseName = "SegmentMesher"
    self.parameterNodeSelector.setMRMLScene( slicer.mrmlScene )
    self.parameterNodeSelector.setToolTip( "Pick parameter set" )
    defaultParametersLayout.addRow("Parameter set: ", self.parameterNodeSelector)

    #
    # Inputs
    #
    inputParametersCollapsibleButton = ctk.ctkCollapsibleButton()
    inputParametersCollapsibleButton.text = "Inputs"
    self.layout.addWidget(inputParametersCollapsibleButton)

    # Layout within the dummy collapsible button
    inputParametersFormLayout = qt.QFormLayout(inputParametersCollapsibleButton)

    self.inputModelSelector = slicer.qMRMLNodeComboBox()
    self.inputModelSelector.nodeTypes = ["vtkMRMLSegmentationNode"]
    self.inputModelSelector.selectNodeUponCreation = True
    self.inputModelSelector.addEnabled = False
    self.inputModelSelector.removeEnabled = False
    self.inputModelSelector.noneEnabled = False
    self.inputModelSelector.showHidden = False
    self.inputModelSelector.showChildNodeTypes = False
    self.inputModelSelector.setMRMLScene( slicer.mrmlScene )
    self.inputModelSelector.setToolTip( "Volumetric mesh will be generated for all visible segments in this segmentation node." )
    inputParametersFormLayout.addRow("Input segmentation: ", self.inputModelSelector)


    self.methodSelectorComboBox = qt.QComboBox()
    self.methodSelectorComboBox.addItem("Cleaver", METHOD_CLEAVER)
    self.methodSelectorComboBox.addItem("TetGen", METHOD_TETGEN)
    inputParametersFormLayout.addRow("Meshing method: ", self.methodSelectorComboBox)

    #
    # Outputs
    #
    outputParametersCollapsibleButton = ctk.ctkCollapsibleButton()
    outputParametersCollapsibleButton.text = "Outputs"
    self.layout.addWidget(outputParametersCollapsibleButton)
    outputParametersFormLayout = qt.QFormLayout(outputParametersCollapsibleButton)

    #
    # output volume selector
    #
    self.outputModelSelector = slicer.qMRMLNodeComboBox()
    self.outputModelSelector.nodeTypes = ["vtkMRMLModelNode"]
    self.outputModelSelector.selectNodeUponCreation = True
    self.outputModelSelector.addEnabled = True
    self.outputModelSelector.renameEnabled = True
    self.outputModelSelector.removeEnabled = True
    self.outputModelSelector.noneEnabled = False
    self.outputModelSelector.showHidden = False
    self.outputModelSelector.showChildNodeTypes = False
    self.outputModelSelector.setMRMLScene( slicer.mrmlScene )
    self.outputModelSelector.setToolTip( "Created volumetric mesh" )
    outputParametersFormLayout.addRow("Output model: ", self.outputModelSelector)

    #
    # Advanced area
    #
    self.advancedCollapsibleButton = ctk.ctkCollapsibleButton()
    self.advancedCollapsibleButton.text = "Advanced"
    self.advancedCollapsibleButton.collapsed = True
    self.layout.addWidget(self.advancedCollapsibleButton)
    advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton)

    self.cleaverAdditionalParametersWidget = qt.QLineEdit()
    self.cleaverAdditionalParametersWidget.setToolTip('Increase --scale parameter value to generate a finer resolution mesh. See description of all parameters in module documentation (Help & Acknowledgment section).')
    advancedFormLayout.addRow("Cleaver meshing options:", self.cleaverAdditionalParametersWidget)
    self.cleaverAdditionalParametersWidget.text = "--scale 0.2 --multiplier 2 --grading 5"

    self.cleaverRemoveBackgroundMeshCheckBox = qt.QCheckBox(" ")
    self.cleaverRemoveBackgroundMeshCheckBox.checked = True
    self.cleaverRemoveBackgroundMeshCheckBox.setToolTip("Remove background mesh (filling segmentation reference geometry box).")
    advancedFormLayout.addRow("Cleaver remove background mesh:", self.cleaverRemoveBackgroundMeshCheckBox)

    self.cleaverPaddingPercentSpinBox = qt.QSpinBox()
    self.cleaverPaddingPercentSpinBox.maximum = 200
    self.cleaverPaddingPercentSpinBox.value = 10
    self.cleaverPaddingPercentSpinBox.suffix=" %"
    self.cleaverPaddingPercentSpinBox.setToolTip("Add padding around the segments to ensure some minimum thickness to the background mesh. Increase value if segments have extrusions towards the edge of the padded bounding box.")
    advancedFormLayout.addRow("Cleaver background padding:", self.cleaverPaddingPercentSpinBox)

    customCleaverPath = self.logic.getCustomCleaverPath()
    self.customCleaverPathSelector = ctk.ctkPathLineEdit()
    self.customCleaverPathSelector.setCurrentPath(customCleaverPath)
    self.customCleaverPathSelector.nameFilters = [self.logic.cleaverFilename]
    self.customCleaverPathSelector.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred)
    self.customCleaverPathSelector.setToolTip("Set cleaver-cli executable path. "
      "If value is empty then cleaver-cli bundled with this extension will be used.")
    advancedFormLayout.addRow("Custom Cleaver executable path:", self.customCleaverPathSelector)

    self.tetGenAdditionalParametersWidget = qt.QLineEdit()
    self.tetGenAdditionalParametersWidget.setToolTip('See description of parameters in module documentation (Help & Acknowledgment section).')
    advancedFormLayout.addRow("TetGen meshing options:", self.tetGenAdditionalParametersWidget)
    self.tetGenAdditionalParametersWidget.text = ""

    customTetGenPath = self.logic.getCustomTetGenPath()
    self.customTetGenPathSelector = ctk.ctkPathLineEdit()
    self.customTetGenPathSelector.setCurrentPath(customTetGenPath)
    self.customTetGenPathSelector.nameFilters = [self.logic.tetGenFilename]
    self.customTetGenPathSelector.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred)
    self.customTetGenPathSelector.setToolTip("Set tetgen executable path. "
      "If value is empty then tetgen bundled with this extension will be used.")
    advancedFormLayout.addRow("Custom TetGen executable path:", self.customTetGenPathSelector)

    self.showDetailedLogDuringExecutionCheckBox = qt.QCheckBox(" ")
    self.showDetailedLogDuringExecutionCheckBox.checked = False
    self.showDetailedLogDuringExecutionCheckBox.setToolTip("Show detailed log during model generation.")
    advancedFormLayout.addRow("Show detailed log:", self.showDetailedLogDuringExecutionCheckBox)

    self.keepTemporaryFilesCheckBox = qt.QCheckBox(" ")
    self.keepTemporaryFilesCheckBox.checked = False
    self.keepTemporaryFilesCheckBox.setToolTip("Keep temporary files (inputs, computed outputs, logs) after the model generation is completed.")

    self.showTemporaryFilesFolderButton = qt.QPushButton("Show temp folder")
    self.showTemporaryFilesFolderButton.toolTip = "Open the folder where temporary files are stored."
    self.showTemporaryFilesFolderButton.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred)

    hbox = qt.QHBoxLayout()
    hbox.addWidget(self.keepTemporaryFilesCheckBox)
    hbox.addWidget(self.showTemporaryFilesFolderButton)
    advancedFormLayout.addRow("Keep temporary files:", hbox)

    #
    # Display
    #
    displayParametersCollapsibleButton = ctk.ctkCollapsibleButton()
    displayParametersCollapsibleButton.text = "Display"
    displayParametersCollapsibleButton.collapsed = True
    self.layout.addWidget(displayParametersCollapsibleButton)
    displayParametersFormLayout = qt.QFormLayout(displayParametersCollapsibleButton)

    self.clipNodeWidget=slicer.qMRMLClipNodeWidget()
    clipNode = slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLClipModelsNode")
    self.clipNodeWidget.setMRMLClipNode(clipNode)
    displayParametersFormLayout.addRow(self.clipNodeWidget)

    #
    # Apply Button
    #
    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.toolTip = "Run the algorithm."
    self.applyButton.enabled = False
    self.layout.addWidget(self.applyButton)

    self.statusLabel = qt.QPlainTextEdit()
    self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
    self.statusLabel.setCenterOnScroll(True)
    self.layout.addWidget(self.statusLabel)

    # connections
    self.applyButton.connect('clicked(bool)', self.onApplyButton)
    self.showTemporaryFilesFolderButton.connect('clicked(bool)', self.onShowTemporaryFilesFolder)
    self.inputModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.updateMRMLFromGUI)
    self.outputModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.updateMRMLFromGUI)
    self.methodSelectorComboBox.connect("currentIndexChanged(int)", self.updateMRMLFromGUI)
    # Immediately update deleteTemporaryFiles in the logic to make it possible to decide to
    # keep the temporary file while the model generation is running
    self.keepTemporaryFilesCheckBox.connect("toggled(bool)", self.onKeepTemporaryFilesToggled)

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

    # Refresh Apply button state
    self.updateMRMLFromGUI()
Пример #5
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        # Instantiate and connect widgets ...
        #
        # Parameters Area
        #
        parametersCollapsibleButton = ctk.ctkCollapsibleButton()
        parametersCollapsibleButton.text = "Input Parameters"
        self.layout.addWidget(parametersCollapsibleButton)

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

        #
        # Select base mesh
        #
        self.modelSelector = slicer.qMRMLNodeComboBox()
        self.modelSelector.nodeTypes = (("vtkMRMLModelNode"), "")
        self.modelSelector.selectNodeUponCreation = False
        self.modelSelector.addEnabled = False
        self.modelSelector.removeEnabled = False
        self.modelSelector.noneEnabled = True
        self.modelSelector.showHidden = False
        self.modelSelector.setMRMLScene(slicer.mrmlScene)
        parametersFormLayout.addRow("Base mesh: ", self.modelSelector)

        #
        # Set spacing tolerance
        #
        self.spacingTolerance = ctk.ctkSliderWidget()
        self.spacingTolerance.singleStep = .1
        self.spacingTolerance.minimum = 0
        self.spacingTolerance.maximum = 10
        self.spacingTolerance.value = 4
        self.spacingTolerance.setToolTip(
            "Set tolerance of spacing as a percentage of the image diagonal")
        parametersFormLayout.addRow("Spacing tolerance: ",
                                    self.spacingTolerance)

        #
        # Parameters Area
        #
        templateCollapsibleButton = ctk.ctkCollapsibleButton()
        templateCollapsibleButton.text = "Template Geometry"
        self.layout.addWidget(templateCollapsibleButton)

        # Layout within the dummy collapsible button
        templateFormLayout = qt.QFormLayout(templateCollapsibleButton)

        #
        # Select geometry of template
        #
        self.OriginalType = qt.QRadioButton()
        self.OriginalType.setChecked(True)
        self.EllipseType = qt.QRadioButton()
        self.SphereType = qt.QRadioButton()
        templateFormLayout.addRow("Original Geometry", self.OriginalType)
        templateFormLayout.addRow("Ellipse", self.EllipseType)
        templateFormLayout.addRow("Sphere", self.SphereType)

        #
        # Specify plane of symmetry
        #
        self.planeSelector = slicer.qMRMLNodeComboBox()
        self.planeSelector.nodeTypes = (("vtkMRMLMarkupsPlaneNode"), "")
        self.planeSelector.enabled = True
        self.planeSelector.selectNodeUponCreation = False
        self.planeSelector.addEnabled = False
        self.planeSelector.removeEnabled = False
        self.planeSelector.noneEnabled = True
        self.planeSelector.showHidden = False
        self.planeSelector.setMRMLScene(slicer.mrmlScene)
        templateFormLayout.addRow("Symmetry plane: ", self.planeSelector)

        #
        # Set template scale factor
        #
        self.scaleFactor = ctk.ctkSliderWidget()
        self.scaleFactor.enabled = False
        self.scaleFactor.singleStep = 1
        self.scaleFactor.minimum = 75
        self.scaleFactor.maximum = 150
        self.scaleFactor.value = 110
        self.scaleFactor.setToolTip(
            "Set  template scale factor as a percentage of the image diagonal")
        templateFormLayout.addRow("Template scale factor : ", self.scaleFactor)

        #
        # Set max projection factor
        #
        self.projectionFactor = ctk.ctkSliderWidget()
        self.projectionFactor.enabled = False
        self.projectionFactor.singleStep = 1
        self.projectionFactor.minimum = 1
        self.projectionFactor.maximum = 200
        self.projectionFactor.value = 200
        self.projectionFactor.setToolTip(
            "Set maximum projection as a percentage of the image diagonal")
        templateFormLayout.addRow("Maximum projection factor : ",
                                  self.projectionFactor)

        #
        # Run Area
        #
        samplingCollapsibleButton = ctk.ctkCollapsibleButton()
        samplingCollapsibleButton.text = "Run Sampling"
        self.layout.addWidget(samplingCollapsibleButton)

        # Layout within the dummy collapsible button
        samplingFormLayout = qt.QFormLayout(samplingCollapsibleButton)
        #
        # Get Subsample Rate Button
        #
        self.getPointNumberButton = qt.QPushButton("Get subsample number")
        self.getPointNumberButton.toolTip = "Output the number of points sampled on the template shape."
        self.getPointNumberButton.enabled = False
        samplingFormLayout.addRow(self.getPointNumberButton)

        #
        # Subsample Information
        #
        self.subsampleInfo = qt.QPlainTextEdit()
        self.subsampleInfo.setPlaceholderText("Subsampling information")
        self.subsampleInfo.setReadOnly(True)
        samplingFormLayout.addRow(self.subsampleInfo)

        #
        # Apply sphere button
        #
        self.applySphereButton = qt.QPushButton("Generate template")
        self.applySphereButton.toolTip = "Generate sampled template shape."
        self.applySphereButton.enabled = False
        samplingFormLayout.addRow(self.applySphereButton)

        #
        # Project Points button
        #
        self.projectPointsButton = qt.QPushButton("Project points to surface")
        self.projectPointsButton.toolTip = "Project the points from the sampled template to the model surface."
        self.projectPointsButton.enabled = False
        samplingFormLayout.addRow(self.projectPointsButton)

        #
        # Clean Points button
        #
        self.cleanButton = qt.QPushButton("Enforce spatial sampling rate")
        self.cleanButton.toolTip = "Remove points spaced closer than the user-specified tolerance."
        self.cleanButton.enabled = False
        samplingFormLayout.addRow(self.cleanButton)

        # connections
        self.modelSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                   self.onSelect)
        self.OriginalType.connect('toggled(bool)', self.onToggleModel)
        self.getPointNumberButton.connect('clicked(bool)',
                                          self.onGetPointNumberButton)
        self.applySphereButton.connect('clicked(bool)',
                                       self.onApplySphereButton)
        self.projectPointsButton.connect('clicked(bool)',
                                         self.onProjectPointsButton)
        self.cleanButton.connect('clicked(bool)', self.onCleanButton)

        # Add vertical spacer
        self.layout.addStretch(1)
Пример #6
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        # Set up tabs to split workflow
        tabsWidget = qt.QTabWidget()
        alignSingleTab = qt.QWidget()
        alignSingleTabLayout = qt.QFormLayout(alignSingleTab)
        alignMultiTab = qt.QWidget()
        alignMultiTabLayout = qt.QFormLayout(alignMultiTab)

        tabsWidget.addTab(alignSingleTab, "Single Alignment")
        tabsWidget.addTab(alignMultiTab, "Batch processing")
        self.layout.addWidget(tabsWidget)

        # Layout within the tab
        alignSingleWidget = ctk.ctkCollapsibleButton()
        alignSingleWidgetLayout = qt.QFormLayout(alignSingleWidget)
        alignSingleWidget.text = "Align and subsample a source and reference mesh "
        alignSingleTabLayout.addRow(alignSingleWidget)

        #
        # Select source mesh
        #
        self.sourceModelSelector = ctk.ctkPathLineEdit()
        self.sourceModelSelector.filters = ctk.ctkPathLineEdit().Files
        self.sourceModelSelector.nameFilters = ["*.ply"]
        alignSingleWidgetLayout.addRow("Source mesh: ",
                                       self.sourceModelSelector)

        #
        # Select source landmarks
        #
        self.sourceFiducialSelector = ctk.ctkPathLineEdit()
        self.sourceFiducialSelector.filters = ctk.ctkPathLineEdit().Files
        self.sourceFiducialSelector.nameFilters = ["*.fcsv"]
        alignSingleWidgetLayout.addRow("Source landmarks: ",
                                       self.sourceFiducialSelector)

        # Select target mesh
        #
        self.targetModelSelector = ctk.ctkPathLineEdit()
        self.targetModelSelector.filters = ctk.ctkPathLineEdit().Files
        self.targetModelSelector.nameFilters = ["*.ply"]
        alignSingleWidgetLayout.addRow("Reference mesh: ",
                                       self.targetModelSelector)

        self.skipScalingCheckBox = qt.QCheckBox()
        self.skipScalingCheckBox.checked = 0
        self.skipScalingCheckBox.setToolTip(
            "If checked, PointCloudRegistration will skip scaling during the alignment (Not recommended)."
        )
        alignSingleWidgetLayout.addRow("Skip scaling",
                                       self.skipScalingCheckBox)

        [
            self.pointDensity, self.normalSearchRadius, self.FPFHSearchRadius,
            self.distanceThreshold, self.maxRANSAC, self.maxRANSACValidation,
            self.ICPDistanceThreshold
        ] = self.addAdvancedMenu(alignSingleWidgetLayout)

        # Advanced tab connections
        self.pointDensity.connect('valueChanged(double)',
                                  self.onChangeAdvanced)
        self.normalSearchRadius.connect('valueChanged(double)',
                                        self.onChangeAdvanced)
        self.FPFHSearchRadius.connect('valueChanged(double)',
                                      self.onChangeAdvanced)
        self.distanceThreshold.connect('valueChanged(double)',
                                       self.onChangeAdvanced)
        self.maxRANSAC.connect('valueChanged(double)', self.onChangeAdvanced)
        self.maxRANSACValidation.connect('valueChanged(double)',
                                         self.onChangeAdvanced)
        self.ICPDistanceThreshold.connect('valueChanged(double)',
                                          self.onChangeAdvanced)

        #
        # Subsample Button
        #
        self.subsampleButton = qt.QPushButton("Run subsampling")
        self.subsampleButton.toolTip = "Run subsampling of the source and reference meshes"
        self.subsampleButton.enabled = False
        alignSingleWidgetLayout.addRow(self.subsampleButton)

        #
        # Subsample Information
        #
        self.subsampleInfo = qt.QPlainTextEdit()
        self.subsampleInfo.setPlaceholderText("Subsampling information")
        self.subsampleInfo.setReadOnly(True)
        alignSingleWidgetLayout.addRow(self.subsampleInfo)

        #
        # Align Button
        #
        self.alignButton = qt.QPushButton("Run rigid alignment")
        self.alignButton.toolTip = "Run rigid alignment of the source and reference meshes"
        self.alignButton.enabled = False
        alignSingleWidgetLayout.addRow(self.alignButton)

        #
        # Plot Aligned Mesh Button
        #
        self.displayMeshButton = qt.QPushButton("Display alignment")
        self.displayMeshButton.toolTip = "Display rigid alignment of the source and references meshes"
        self.displayMeshButton.enabled = False
        alignSingleWidgetLayout.addRow(self.displayMeshButton)

        # connections
        self.sourceModelSelector.connect('validInputChanged(bool)',
                                         self.onSelect)
        self.sourceFiducialSelector.connect('validInputChanged(bool)',
                                            self.onSelect)
        self.targetModelSelector.connect('validInputChanged(bool)',
                                         self.onSelect)
        self.subsampleButton.connect('clicked(bool)', self.onSubsampleButton)
        self.alignButton.connect('clicked(bool)', self.onAlignButton)
        self.displayMeshButton.connect('clicked(bool)',
                                       self.onDisplayMeshButton)

        # Layout within the multiprocessing tab
        alignMultiWidget = ctk.ctkCollapsibleButton()
        alignMultiWidgetLayout = qt.QFormLayout(alignMultiWidget)
        alignMultiWidget.text = "Alings landmarks from multiple specimens to a reference 3d model (mesh)"
        alignMultiTabLayout.addRow(alignMultiWidget)

        #
        # Select source mesh
        #
        self.sourceModelMultiSelector = ctk.ctkPathLineEdit()
        self.sourceModelMultiSelector.filters = ctk.ctkPathLineEdit.Dirs
        self.sourceModelMultiSelector.toolTip = "Select the directory containing the source meshes"
        alignMultiWidgetLayout.addRow("Source mesh directory: ",
                                      self.sourceModelMultiSelector)

        #
        # Select source landmark file
        #
        self.sourceFiducialMultiSelector = ctk.ctkPathLineEdit()
        self.sourceFiducialMultiSelector.filters = ctk.ctkPathLineEdit.Dirs
        self.sourceFiducialMultiSelector.toolTip = "Select the directory containing the source landmarks"
        alignMultiWidgetLayout.addRow("Source landmark directory: ",
                                      self.sourceFiducialMultiSelector)

        # Select target mesh directory
        #
        self.targetModelMultiSelector = ctk.ctkPathLineEdit()
        self.targetModelMultiSelector.filters = ctk.ctkPathLineEdit().Files
        self.targetModelMultiSelector.nameFilters = ["*.ply"]
        alignMultiWidgetLayout.addRow("Reference mesh: ",
                                      self.targetModelMultiSelector)

        # Select output landmark directory
        #
        self.landmarkOutputSelector = ctk.ctkPathLineEdit()
        self.landmarkOutputSelector.filters = ctk.ctkPathLineEdit.Dirs
        self.landmarkOutputSelector.toolTip = "Select the output directory where the landmarks will be saved"
        alignMultiWidgetLayout.addRow("Output landmark directory: ",
                                      self.landmarkOutputSelector)

        self.skipScalingMultiCheckBox = qt.QCheckBox()
        self.skipScalingMultiCheckBox.checked = 0
        self.skipScalingMultiCheckBox.setToolTip(
            "If checked, PointCloudRegistration will skip scaling during the alignment."
        )
        alignMultiWidgetLayout.addRow("Skip scaling",
                                      self.skipScalingMultiCheckBox)

        [
            self.pointDensityMulti, self.normalSearchRadiusMulti,
            self.FPFHSearchRadiusMulti, self.distanceThresholdMulti,
            self.maxRANSACMulti, self.maxRANSACValidationMulti,
            self.ICPDistanceThresholdMulti
        ] = self.addAdvancedMenu(alignMultiWidgetLayout)

        #
        # Run landmarking Button
        #
        self.applyLandmarkMultiButton = qt.QPushButton(
            "Run PointCloud Registration")
        self.applyLandmarkMultiButton.toolTip = "Align the source meshes and landmarks with a reference mesh"
        self.applyLandmarkMultiButton.enabled = False
        alignMultiWidgetLayout.addRow(self.applyLandmarkMultiButton)

        # connections
        self.sourceModelMultiSelector.connect('validInputChanged(bool)',
                                              self.onSelectMultiProcess)
        self.sourceFiducialMultiSelector.connect('validInputChanged(bool)',
                                                 self.onSelectMultiProcess)
        self.targetModelMultiSelector.connect('validInputChanged(bool)',
                                              self.onSelectMultiProcess)
        self.landmarkOutputSelector.connect('validInputChanged(bool)',
                                            self.onSelectMultiProcess)
        self.skipScalingMultiCheckBox.connect('validInputChanged(bool)',
                                              self.onSelectMultiProcess)
        self.applyLandmarkMultiButton.connect('clicked(bool)',
                                              self.onApplyLandmarkMulti)

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

        # Advanced tab connections
        self.pointDensityMulti.connect('valueChanged(double)',
                                       self.updateParameterDictionary)
        self.normalSearchRadiusMulti.connect('valueChanged(double)',
                                             self.updateParameterDictionary)
        self.FPFHSearchRadiusMulti.connect('valueChanged(double)',
                                           self.updateParameterDictionary)
        self.distanceThresholdMulti.connect('valueChanged(double)',
                                            self.updateParameterDictionary)
        self.maxRANSACMulti.connect('valueChanged(double)',
                                    self.updateParameterDictionary)
        self.maxRANSACValidationMulti.connect('valueChanged(double)',
                                              self.updateParameterDictionary)
        self.ICPDistanceThresholdMulti.connect('valueChanged(double)',
                                               self.updateParameterDictionary)

        # initialize the parameter dictionary from single run parameters
        self.parameterDictionary = {
            "pointDensity": self.pointDensity.value,
            "normalSearchRadius": self.normalSearchRadius.value,
            "FPFHSearchRadius": self.FPFHSearchRadius.value,
            "distanceThreshold": self.distanceThreshold.value,
            "maxRANSAC": int(self.maxRANSAC.value),
            "maxRANSACValidation": int(self.maxRANSACValidation.value),
            "ICPDistanceThreshold": self.ICPDistanceThreshold.value
        }
        # initialize the parameter dictionary from multi run parameters
        self.parameterDictionaryMulti = {
            "pointDensity": self.pointDensityMulti.value,
            "normalSearchRadius": self.normalSearchRadiusMulti.value,
            "FPFHSearchRadius": self.FPFHSearchRadiusMulti.value,
            "distanceThreshold": self.distanceThresholdMulti.value,
            "maxRANSAC": int(self.maxRANSACMulti.value),
            "maxRANSACValidation": int(self.maxRANSACValidationMulti.value),
            "ICPDistanceThreshold": self.ICPDistanceThresholdMulti.value
        }
Пример #7
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        # Instantiate and connect widgets ...

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

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

        self.inputDirSelector = ctk.ctkPathLineEdit()
        self.inputDirSelector.filters = ctk.ctkPathLineEdit.Dirs
        self.inputDirSelector.settingKey = 'DICOMPatcherInputDir'
        parametersFormLayout.addRow("Input DICOM directory:", self.inputDirSelector)

        self.outputDirSelector = ctk.ctkPathLineEdit()
        self.outputDirSelector.filters = ctk.ctkPathLineEdit.Dirs
        self.outputDirSelector.settingKey = 'DICOMPatcherOutputDir'
        parametersFormLayout.addRow("Output DICOM directory:", self.outputDirSelector)

        self.normalizeFileNamesCheckBox = qt.QCheckBox()
        self.normalizeFileNamesCheckBox.checked = True
        self.normalizeFileNamesCheckBox.setToolTip("Replace file and folder names with automatically generated names."
                                                   " Fixes errors caused by file path containins special characters or being too long.")
        parametersFormLayout.addRow("Normalize file names", self.normalizeFileNamesCheckBox)

        self.forceSamePatientNameIdInEachDirectoryCheckBox = qt.QCheckBox()
        self.forceSamePatientNameIdInEachDirectoryCheckBox.checked = False
        self.forceSamePatientNameIdInEachDirectoryCheckBox.setToolTip("Generate patient name and ID from the first file in a directory"
                                                                      " and force all other files in the same directory to have the same patient name and ID."
                                                                      " Enable this option if a separate patient directory is created for each patched file.")
        parametersFormLayout.addRow("Force same patient name and ID in each directory", self.forceSamePatientNameIdInEachDirectoryCheckBox)

        self.forceSameSeriesInstanceUidInEachDirectoryCheckBox = qt.QCheckBox()
        self.forceSameSeriesInstanceUidInEachDirectoryCheckBox.checked = False
        self.forceSameSeriesInstanceUidInEachDirectoryCheckBox.setToolTip("Generate a new series instance UID for each directory"
                                                                          " and set it in all files in that same directory."
                                                                          " Enable this option to force placing all frames in a folder into a single volume.")
        parametersFormLayout.addRow("Force same series instance UID in each directory", self.forceSameSeriesInstanceUidInEachDirectoryCheckBox)

        self.generateMissingIdsCheckBox = qt.QCheckBox()
        self.generateMissingIdsCheckBox.checked = True
        self.generateMissingIdsCheckBox.setToolTip("Generate missing patient, study, series IDs. It is assumed that"
                                                   " all files in a directory belong to the same series. Fixes error caused by too aggressive anonymization"
                                                   " or incorrect DICOM image converters.")
        parametersFormLayout.addRow("Generate missing patient/study/series IDs", self.generateMissingIdsCheckBox)

        self.generateImagePositionFromSliceThicknessCheckBox = qt.QCheckBox()
        self.generateImagePositionFromSliceThicknessCheckBox.checked = True
        self.generateImagePositionFromSliceThicknessCheckBox.setToolTip("Generate 'image position sequence' for"
                                                                        " multi-frame files that only have 'SliceThickness' field. Fixes error in Dolphin 3D CBCT scanners.")
        parametersFormLayout.addRow("Generate slice position for multi-frame volumes", self.generateImagePositionFromSliceThicknessCheckBox)

        self.anonymizeDicomCheckBox = qt.QCheckBox()
        self.anonymizeDicomCheckBox.checked = False
        self.anonymizeDicomCheckBox.setToolTip("If checked, then some patient identifiable information will be removed"
                                               " from the patched DICOM files. There are many fields that can identify a patient, this function does not remove all of them.")
        parametersFormLayout.addRow("Partially anonymize", self.anonymizeDicomCheckBox)

        #
        # Patch Button
        #
        self.patchButton = qt.QPushButton("Patch")
        self.patchButton.toolTip = "Fix DICOM files in input directory and write them to output directory"
        parametersFormLayout.addRow(self.patchButton)

        #
        # Import Button
        #
        self.importButton = qt.QPushButton("Import to DICOM database")
        self.importButton.toolTip = "Import DICOM files in output directory into the application's DICOM database"
        parametersFormLayout.addRow(self.importButton)

        # connections
        self.patchButton.connect('clicked(bool)', self.onPatchButton)
        self.importButton.connect('clicked(bool)', self.onImportButton)

        self.statusLabel = qt.QPlainTextEdit()
        self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
        parametersFormLayout.addRow(self.statusLabel)

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

        self.logic = DICOMPatcherLogic()
        self.logic.logCallback = self.addLog
Пример #8
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        self.logic = ScreenCaptureLogic()
        self.logic.logCallback = self.addLog
        self.viewNodeType = None
        self.animationMode = None

        # Instantiate and connect widgets ...

        #
        # Input area
        #
        inputCollapsibleButton = ctk.ctkCollapsibleButton()
        inputCollapsibleButton.text = "Input"
        self.layout.addWidget(inputCollapsibleButton)
        inputFormLayout = qt.QFormLayout(inputCollapsibleButton)

        # Input view selector
        self.viewNodeSelector = slicer.qMRMLNodeComboBox()
        self.viewNodeSelector.nodeTypes = [
            "vtkMRMLSliceNode", "vtkMRMLViewNode"
        ]
        self.viewNodeSelector.addEnabled = False
        self.viewNodeSelector.removeEnabled = False
        self.viewNodeSelector.noneEnabled = False
        self.viewNodeSelector.showHidden = False
        self.viewNodeSelector.showChildNodeTypes = False
        self.viewNodeSelector.setMRMLScene(slicer.mrmlScene)
        self.viewNodeSelector.setToolTip(
            "Contents of this slice or 3D view will be captured.")
        inputFormLayout.addRow("View to capture: ", self.viewNodeSelector)

        # Mode
        self.animationModeWidget = qt.QComboBox()
        self.animationModeWidget.setToolTip(
            "Select the property that will be adjusted")
        inputFormLayout.addRow("Animation mode:", self.animationModeWidget)

        # Slice start offset position
        self.sliceStartOffsetSliderLabel = qt.QLabel("Start sweep offset:")
        self.sliceStartOffsetSliderWidget = ctk.ctkSliderWidget()
        self.sliceStartOffsetSliderWidget.singleStep = 30
        self.sliceStartOffsetSliderWidget.minimum = -100
        self.sliceStartOffsetSliderWidget.maximum = 100
        self.sliceStartOffsetSliderWidget.value = 0
        self.sliceStartOffsetSliderWidget.setToolTip(
            "Start slice sweep offset.")
        inputFormLayout.addRow(self.sliceStartOffsetSliderLabel,
                               self.sliceStartOffsetSliderWidget)

        # Slice end offset position
        self.sliceEndOffsetSliderLabel = qt.QLabel("End sweep offset:")
        self.sliceEndOffsetSliderWidget = ctk.ctkSliderWidget()
        self.sliceEndOffsetSliderWidget.singleStep = 5
        self.sliceEndOffsetSliderWidget.minimum = -100
        self.sliceEndOffsetSliderWidget.maximum = 100
        self.sliceEndOffsetSliderWidget.value = 0
        self.sliceEndOffsetSliderWidget.setToolTip("End slice sweep offset.")
        inputFormLayout.addRow(self.sliceEndOffsetSliderLabel,
                               self.sliceEndOffsetSliderWidget)

        # 3D start rotation
        self.startRotationSliderLabel = qt.QLabel("Start rotation angle:")
        self.startRotationSliderWidget = ctk.ctkSliderWidget()
        self.startRotationSliderWidget.singleStep = 5
        self.startRotationSliderWidget.minimum = 0
        self.startRotationSliderWidget.maximum = 180
        self.startRotationSliderWidget.value = 180
        self.startRotationSliderWidget.setToolTip(
            "Rotation angle for the first image, relative to current orientation."
        )
        inputFormLayout.addRow(self.startRotationSliderLabel,
                               self.startRotationSliderWidget)

        # 3D end rotation
        self.endRotationSliderLabel = qt.QLabel("End rotation angle:")
        self.endRotationSliderWidget = ctk.ctkSliderWidget()
        self.endRotationSliderWidget.singleStep = 5
        self.endRotationSliderWidget.minimum = 0
        self.endRotationSliderWidget.maximum = 180
        self.endRotationSliderWidget.value = 180
        self.endRotationSliderWidget.setToolTip(
            "Rotation angle for the last image, relative to current orientation."
        )
        inputFormLayout.addRow(self.endRotationSliderLabel,
                               self.endRotationSliderWidget)

        # Sequence browser node selector
        self.sequenceBrowserNodeSelectorLabel = qt.QLabel(
            "End rotation angle:")
        self.sequenceBrowserNodeSelectorWidget = slicer.qMRMLNodeComboBox()
        self.sequenceBrowserNodeSelectorWidget.nodeTypes = [
            "vtkMRMLSequenceBrowserNode"
        ]
        self.sequenceBrowserNodeSelectorWidget.addEnabled = False
        self.sequenceBrowserNodeSelectorWidget.removeEnabled = False
        self.sequenceBrowserNodeSelectorWidget.noneEnabled = False
        self.sequenceBrowserNodeSelectorWidget.showHidden = False
        self.sequenceBrowserNodeSelectorWidget.setMRMLScene(slicer.mrmlScene)
        self.sequenceBrowserNodeSelectorWidget.setToolTip(
            "Items defined by this sequence browser will be replayed.")
        inputFormLayout.addRow(self.sequenceBrowserNodeSelectorLabel,
                               self.sequenceBrowserNodeSelectorWidget)

        # Sequence start index
        self.sequenceStartItemIndexLabel = qt.QLabel("Start index:")
        self.sequenceStartItemIndexWidget = ctk.ctkSliderWidget()
        self.sequenceStartItemIndexWidget.minimum = 0
        self.sequenceStartItemIndexWidget.decimals = 0
        self.sequenceStartItemIndexWidget.setToolTip(
            "First item in the sequence to capture.")
        inputFormLayout.addRow(self.sequenceStartItemIndexLabel,
                               self.sequenceStartItemIndexWidget)

        # Sequence end index
        self.sequenceEndItemIndexLabel = qt.QLabel("End index:")
        self.sequenceEndItemIndexWidget = ctk.ctkSliderWidget()
        self.sequenceEndItemIndexWidget.singleStep = 10
        self.sequenceEndItemIndexWidget.minimum = 0
        self.sequenceEndItemIndexWidget.decimals = 0
        self.sequenceEndItemIndexWidget.setToolTip(
            "Last item in the sequence to capture.")
        inputFormLayout.addRow(self.sequenceEndItemIndexLabel,
                               self.sequenceEndItemIndexWidget)

        #
        # Output area
        #
        outputCollapsibleButton = ctk.ctkCollapsibleButton()
        outputCollapsibleButton.text = "Output"
        self.layout.addWidget(outputCollapsibleButton)
        outputFormLayout = qt.QFormLayout(outputCollapsibleButton)

        # Number of steps value
        self.numberOfStepsSliderWidget = ctk.ctkSliderWidget()
        self.numberOfStepsSliderWidget.singleStep = 10
        self.numberOfStepsSliderWidget.minimum = 2
        self.numberOfStepsSliderWidget.maximum = 150
        self.numberOfStepsSliderWidget.value = 31
        self.numberOfStepsSliderWidget.decimals = 0
        self.numberOfStepsSliderWidget.setToolTip(
            "Number of images extracted between start and stop positions.")
        outputFormLayout.addRow("Number of images:",
                                self.numberOfStepsSliderWidget)

        # Output directory selector
        self.outputDirSelector = ctk.ctkPathLineEdit()
        self.outputDirSelector.filters = ctk.ctkPathLineEdit.Dirs
        self.outputDirSelector.settingKey = 'ScreenCaptureOutputDir'
        outputFormLayout.addRow("Output directory:", self.outputDirSelector)
        if not self.outputDirSelector.currentPath:
            defaultOutputPath = os.path.abspath(
                os.path.join(slicer.app.defaultScenePath, 'SlicerCapture'))
            self.outputDirSelector.setCurrentPath(defaultOutputPath)

        self.videoExportCheckBox = qt.QCheckBox()
        self.videoExportCheckBox.checked = False
        self.videoExportCheckBox.setToolTip(
            "If checked, exported images will be written as a video file."
            " Requires setting of ffmpeg executable path in Advanced section.")
        outputFormLayout.addRow("Video export:", self.videoExportCheckBox)

        self.videoFileNameWidget = qt.QLineEdit()
        self.videoFileNameWidget.setToolTip(
            "String that defines file name, type, and numbering scheme. Default: capture.avi."
        )
        self.videoFileNameWidget.text = "SlicerCapture.avi"
        self.videoFileNameWidget.setEnabled(False)
        outputFormLayout.addRow("Video file name:", self.videoFileNameWidget)

        self.videoLengthSliderWidget = ctk.ctkSliderWidget()
        self.videoLengthSliderWidget.singleStep = 0.1
        self.videoLengthSliderWidget.minimum = 0.1
        self.videoLengthSliderWidget.maximum = 30
        self.videoLengthSliderWidget.value = 5
        self.videoLengthSliderWidget.suffix = "s"
        self.videoLengthSliderWidget.decimals = 1
        self.videoLengthSliderWidget.setToolTip(
            "Length of the exported video in seconds.")
        self.videoLengthSliderWidget.setEnabled(False)
        outputFormLayout.addRow("Video length:", self.videoLengthSliderWidget)

        #
        # Advanced area
        #
        self.advancedCollapsibleButton = ctk.ctkCollapsibleButton()
        self.advancedCollapsibleButton.text = "Advanced"
        self.advancedCollapsibleButton.collapsed = True
        outputFormLayout.addRow(self.advancedCollapsibleButton)
        advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton)

        self.fileNamePatternWidget = qt.QLineEdit()
        self.fileNamePatternWidget.setToolTip(
            "String that defines file name, type, and numbering scheme. Default: image%05d.png."
        )
        self.fileNamePatternWidget.text = "image_%05d.png"
        advancedFormLayout.addRow("Image file name pattern:",
                                  self.fileNamePatternWidget)

        ffmpegPath = self.logic.getFfmpegPath()
        self.ffmpegPathSelector = ctk.ctkPathLineEdit()
        self.ffmpegPathSelector.setCurrentPath(ffmpegPath)
        self.ffmpegPathSelector.nameFilters = ['ffmpeg.exe', 'ffmpeg']
        self.ffmpegPathSelector.setMaximumWidth(300)
        self.ffmpegPathSelector.setToolTip(
            "Set the path to ffmpeg executable. Download from: https://www.ffmpeg.org/"
        )
        advancedFormLayout.addRow("ffmpeg executable:",
                                  self.ffmpegPathSelector)

        self.extraVideoOptionsWidget = qt.QComboBox()
        self.extraVideoOptionsWidget.addItem("-c:v mpeg4 -qscale:v 5")
        self.extraVideoOptionsWidget.addItem(
            "-c:v libx264 -preset veryslow -qp 0")
        self.extraVideoOptionsWidget.addItem(
            "-f mp4 -vcodec libx264 -pix_fmt yuv420p")
        self.extraVideoOptionsWidget.setEditable(True)
        self.extraVideoOptionsWidget.setToolTip(
            '<html>\n'
            '  <p>Additional video conversion options passed to ffmpeg.</p>'
            '  <p><b>Examples:</b>'
            '  <ul>'
            '    <li><b>MPEG4: </b>-c:v mpeg4 -qscale:v 5</li>'
            '    <li><b>H264: </b>-c:v libx264 -preset veryslow -qp 0</li>'
            '    <li><b>Quicktime: </b>-f mp4 -vcodec libx264 -pix_fmt yuv420p</li>'
            '  </ul></p>'
            '  <p>See more encoding options at:'
            '  <i>https://trac.ffmpeg.org/wiki/Encode/H.264</i> and'
            '  <i>https://trac.ffmpeg.org/wiki/Encode/MPEG-4</i></p>'
            '</html>')
        advancedFormLayout.addRow("Video extra options:",
                                  self.extraVideoOptionsWidget)

        # Capture button
        self.captureButton = qt.QPushButton("Capture")
        self.captureButton.toolTip = "Capture slice sweep to image sequence."
        outputFormLayout.addRow(self.captureButton)

        self.statusLabel = qt.QPlainTextEdit()
        self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
        self.statusLabel.setCenterOnScroll(True)
        outputFormLayout.addRow(self.statusLabel)

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

        # connections
        self.captureButton.connect('clicked(bool)', self.onCaptureButton)
        self.viewNodeSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                      self.updateViewOptions)
        self.animationModeWidget.connect("currentIndexChanged(int)",
                                         self.updateViewOptions)
        self.sliceStartOffsetSliderWidget.connect('valueChanged(double)',
                                                  self.setSliceOffset)
        self.sliceEndOffsetSliderWidget.connect('valueChanged(double)',
                                                self.setSliceOffset)
        self.sequenceBrowserNodeSelectorWidget.connect(
            "currentNodeChanged(vtkMRMLNode*)", self.updateViewOptions)
        self.sequenceStartItemIndexWidget.connect('valueChanged(double)',
                                                  self.setSequenceItemIndex)
        self.sequenceEndItemIndexWidget.connect('valueChanged(double)',
                                                self.setSequenceItemIndex)
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.fileNamePatternWidget,
                                         'setDisabled(bool)')
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.videoFileNameWidget,
                                         'setEnabled(bool)')
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.videoLengthSliderWidget,
                                         'setEnabled(bool)')

        self.updateViewOptions()
Пример #9
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        self.logic = ScreenCaptureLogic()
        self.logic.logCallback = self.addLog
        self.viewNodeType = None
        self.animationMode = None
        self.createdOutputFile = None

        # Instantiate and connect widgets ...

        #
        # Input area
        #
        inputCollapsibleButton = ctk.ctkCollapsibleButton()
        inputCollapsibleButton.text = "Input"
        self.layout.addWidget(inputCollapsibleButton)
        inputFormLayout = qt.QFormLayout(inputCollapsibleButton)

        # Input view selector
        self.viewNodeSelector = slicer.qMRMLNodeComboBox()
        self.viewNodeSelector.nodeTypes = [
            "vtkMRMLSliceNode", "vtkMRMLViewNode"
        ]
        self.viewNodeSelector.addEnabled = False
        self.viewNodeSelector.removeEnabled = False
        self.viewNodeSelector.noneEnabled = False
        self.viewNodeSelector.showHidden = False
        self.viewNodeSelector.showChildNodeTypes = False
        self.viewNodeSelector.setMRMLScene(slicer.mrmlScene)
        self.viewNodeSelector.setToolTip(
            "Contents of this slice or 3D view will be captured.")
        inputFormLayout.addRow("View to capture: ", self.viewNodeSelector)

        # Mode
        self.animationModeWidget = qt.QComboBox()
        self.animationModeWidget.setToolTip(
            "Select the property that will be adjusted")
        inputFormLayout.addRow("Animation mode:", self.animationModeWidget)

        # Slice start offset position
        self.sliceStartOffsetSliderLabel = qt.QLabel("Start sweep offset:")
        self.sliceStartOffsetSliderWidget = ctk.ctkSliderWidget()
        self.sliceStartOffsetSliderWidget.singleStep = 30
        self.sliceStartOffsetSliderWidget.minimum = -100
        self.sliceStartOffsetSliderWidget.maximum = 100
        self.sliceStartOffsetSliderWidget.value = 0
        self.sliceStartOffsetSliderWidget.setToolTip(
            "Start slice sweep offset.")
        inputFormLayout.addRow(self.sliceStartOffsetSliderLabel,
                               self.sliceStartOffsetSliderWidget)

        # Slice end offset position
        self.sliceEndOffsetSliderLabel = qt.QLabel("End sweep offset:")
        self.sliceEndOffsetSliderWidget = ctk.ctkSliderWidget()
        self.sliceEndOffsetSliderWidget.singleStep = 5
        self.sliceEndOffsetSliderWidget.minimum = -100
        self.sliceEndOffsetSliderWidget.maximum = 100
        self.sliceEndOffsetSliderWidget.value = 0
        self.sliceEndOffsetSliderWidget.setToolTip("End slice sweep offset.")
        inputFormLayout.addRow(self.sliceEndOffsetSliderLabel,
                               self.sliceEndOffsetSliderWidget)

        # 3D start rotation
        self.rotationSliderLabel = qt.QLabel("Rotation range:")
        self.rotationSliderWidget = ctk.ctkRangeWidget()
        self.rotationSliderWidget.singleStep = 5
        self.rotationSliderWidget.minimum = -180
        self.rotationSliderWidget.maximum = 180
        self.rotationSliderWidget.minimumValue = -180
        self.rotationSliderWidget.maximumValue = 180
        self.rotationSliderWidget.setToolTip(
            "View rotation range, relative to current view orientation.")
        inputFormLayout.addRow(self.rotationSliderLabel,
                               self.rotationSliderWidget)

        # Sequence browser node selector
        self.sequenceBrowserNodeSelectorLabel = qt.QLabel("Sequence:")
        self.sequenceBrowserNodeSelectorWidget = slicer.qMRMLNodeComboBox()
        self.sequenceBrowserNodeSelectorWidget.nodeTypes = [
            "vtkMRMLSequenceBrowserNode"
        ]
        self.sequenceBrowserNodeSelectorWidget.addEnabled = False
        self.sequenceBrowserNodeSelectorWidget.removeEnabled = False
        self.sequenceBrowserNodeSelectorWidget.noneEnabled = False
        self.sequenceBrowserNodeSelectorWidget.showHidden = False
        self.sequenceBrowserNodeSelectorWidget.setMRMLScene(slicer.mrmlScene)
        self.sequenceBrowserNodeSelectorWidget.setToolTip(
            "Items defined by this sequence browser will be replayed.")
        inputFormLayout.addRow(self.sequenceBrowserNodeSelectorLabel,
                               self.sequenceBrowserNodeSelectorWidget)

        # Sequence start index
        self.sequenceStartItemIndexLabel = qt.QLabel("Start index:")
        self.sequenceStartItemIndexWidget = ctk.ctkSliderWidget()
        self.sequenceStartItemIndexWidget.minimum = 0
        self.sequenceStartItemIndexWidget.decimals = 0
        self.sequenceStartItemIndexWidget.setToolTip(
            "First item in the sequence to capture.")
        inputFormLayout.addRow(self.sequenceStartItemIndexLabel,
                               self.sequenceStartItemIndexWidget)

        # Sequence end index
        self.sequenceEndItemIndexLabel = qt.QLabel("End index:")
        self.sequenceEndItemIndexWidget = ctk.ctkSliderWidget()
        self.sequenceEndItemIndexWidget.minimum = 0
        self.sequenceEndItemIndexWidget.decimals = 0
        self.sequenceEndItemIndexWidget.setToolTip(
            "Last item in the sequence to capture.")
        inputFormLayout.addRow(self.sequenceEndItemIndexLabel,
                               self.sequenceEndItemIndexWidget)

        #
        # Output area
        #
        outputCollapsibleButton = ctk.ctkCollapsibleButton()
        outputCollapsibleButton.text = "Output"
        self.layout.addWidget(outputCollapsibleButton)
        outputFormLayout = qt.QFormLayout(outputCollapsibleButton)

        # Number of steps value
        self.numberOfStepsSliderWidget = ctk.ctkSliderWidget()
        self.numberOfStepsSliderWidget.singleStep = 10
        self.numberOfStepsSliderWidget.minimum = 2
        self.numberOfStepsSliderWidget.maximum = 600
        self.numberOfStepsSliderWidget.value = 31
        self.numberOfStepsSliderWidget.decimals = 0
        self.numberOfStepsSliderWidget.setToolTip(
            "Number of images extracted between start and stop positions.")
        outputFormLayout.addRow("Number of images:",
                                self.numberOfStepsSliderWidget)

        # Output directory selector
        self.outputDirSelector = ctk.ctkPathLineEdit()
        self.outputDirSelector.filters = ctk.ctkPathLineEdit.Dirs
        self.outputDirSelector.settingKey = 'ScreenCaptureOutputDir'
        outputFormLayout.addRow("Output directory:", self.outputDirSelector)
        if not self.outputDirSelector.currentPath:
            defaultOutputPath = os.path.abspath(
                os.path.join(slicer.app.defaultScenePath, 'SlicerCapture'))
            self.outputDirSelector.setCurrentPath(defaultOutputPath)

        self.videoExportCheckBox = qt.QCheckBox(" ")
        self.videoExportCheckBox.checked = False
        self.videoExportCheckBox.setToolTip(
            "If checked, exported images will be written as a video file."
            " Requires setting of ffmpeg executable path in Advanced section.")

        self.videoFormatWidget = qt.QComboBox()
        self.videoFormatWidget.enabled = False
        self.videoFormatWidget.setSizePolicy(qt.QSizePolicy.Expanding,
                                             qt.QSizePolicy.Preferred)
        for videoFormatPreset in self.logic.videoFormatPresets:
            self.videoFormatWidget.addItem(videoFormatPreset["name"])

        hbox = qt.QHBoxLayout()
        hbox.addWidget(self.videoExportCheckBox)
        hbox.addWidget(self.videoFormatWidget)
        outputFormLayout.addRow("Video export:", hbox)

        self.videoFileNameWidget = qt.QLineEdit()
        self.videoFileNameWidget.setToolTip(
            "String that defines file name and type.")
        self.videoFileNameWidget.text = "SlicerCapture.avi"
        self.videoFileNameWidget.setEnabled(False)
        outputFormLayout.addRow("Video file name:", self.videoFileNameWidget)

        self.videoLengthSliderWidget = ctk.ctkSliderWidget()
        self.videoLengthSliderWidget.singleStep = 0.1
        self.videoLengthSliderWidget.minimum = 0.1
        self.videoLengthSliderWidget.maximum = 30
        self.videoLengthSliderWidget.value = 5
        self.videoLengthSliderWidget.suffix = "s"
        self.videoLengthSliderWidget.decimals = 1
        self.videoLengthSliderWidget.setToolTip(
            "Length of the exported video in seconds.")
        self.videoLengthSliderWidget.setEnabled(False)
        outputFormLayout.addRow("Video length:", self.videoLengthSliderWidget)

        #
        # Advanced area
        #
        self.advancedCollapsibleButton = ctk.ctkCollapsibleButton()
        self.advancedCollapsibleButton.text = "Advanced"
        self.advancedCollapsibleButton.collapsed = True
        outputFormLayout.addRow(self.advancedCollapsibleButton)
        advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton)

        ffmpegPath = self.logic.getFfmpegPath()
        self.ffmpegPathSelector = ctk.ctkPathLineEdit()
        self.ffmpegPathSelector.setCurrentPath(ffmpegPath)
        self.ffmpegPathSelector.nameFilters = [
            self.logic.getFfmpegExecutableFilename()
        ]
        self.ffmpegPathSelector.setSizePolicy(qt.QSizePolicy.MinimumExpanding,
                                              qt.QSizePolicy.Preferred)
        self.ffmpegPathSelector.setToolTip(
            "Set the path to ffmpeg executable. Download from: https://www.ffmpeg.org/"
        )
        advancedFormLayout.addRow("ffmpeg executable:",
                                  self.ffmpegPathSelector)

        self.videoExportFfmpegWarning = qt.QLabel(
            '<qt><b><font color="red">Set valid ffmpeg executable path! ' +
            '<a href="http://wiki.slicer.org/slicerWiki/index.php/Documentation/Nightly/Modules/ScreenCapture#Setting_up_ffmpeg">Help...</a></font></b></qt>'
        )
        self.videoExportFfmpegWarning.connect('linkActivated(QString)',
                                              self.openURL)
        self.videoExportFfmpegWarning.setVisible(False)
        advancedFormLayout.addRow("", self.videoExportFfmpegWarning)

        self.extraVideoOptionsWidget = qt.QLineEdit()
        self.extraVideoOptionsWidget.setToolTip(
            'Additional video conversion options passed to ffmpeg. Parameters -i (input files), -y'
            +
            '(overwrite without asking), -r (frame rate), -start_number are specified by the module and therefore'
            + 'should not be included in this list.')
        advancedFormLayout.addRow("Video extra options:",
                                  self.extraVideoOptionsWidget)

        self.fileNamePatternWidget = qt.QLineEdit()
        self.fileNamePatternWidget.setToolTip(
            "String that defines file name, type, and numbering scheme. Default: image%05d.png."
        )
        self.fileNamePatternWidget.text = "image_%05d.png"
        advancedFormLayout.addRow("Image file name pattern:",
                                  self.fileNamePatternWidget)

        # Capture button
        self.captureButton = qt.QPushButton("Capture")
        self.captureButton.toolTip = "Capture slice sweep to image sequence."
        self.showCreatedOutputFileButton = qt.QPushButton()
        self.showCreatedOutputFileButton.setIcon(qt.QIcon(':Icons/Go.png'))
        self.showCreatedOutputFileButton.setMaximumWidth(60)
        self.showCreatedOutputFileButton.enabled = False
        self.showCreatedOutputFileButton.toolTip = "Show created output file."
        hbox = qt.QHBoxLayout()
        hbox.addWidget(self.captureButton)
        hbox.addWidget(self.showCreatedOutputFileButton)
        outputFormLayout.addRow(hbox)

        self.statusLabel = qt.QPlainTextEdit()
        self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
        self.statusLabel.setCenterOnScroll(True)
        outputFormLayout.addRow(self.statusLabel)

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

        # connections
        self.captureButton.connect('clicked(bool)', self.onCaptureButton)
        self.showCreatedOutputFileButton.connect('clicked(bool)',
                                                 self.onShowCreatedOutputFile)
        self.viewNodeSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                      self.updateViewOptions)
        self.animationModeWidget.connect("currentIndexChanged(int)",
                                         self.updateViewOptions)
        self.sliceStartOffsetSliderWidget.connect('valueChanged(double)',
                                                  self.setSliceOffset)
        self.sliceEndOffsetSliderWidget.connect('valueChanged(double)',
                                                self.setSliceOffset)
        self.sequenceBrowserNodeSelectorWidget.connect(
            "currentNodeChanged(vtkMRMLNode*)", self.updateViewOptions)
        self.sequenceStartItemIndexWidget.connect('valueChanged(double)',
                                                  self.setSequenceItemIndex)
        self.sequenceEndItemIndexWidget.connect('valueChanged(double)',
                                                self.setSequenceItemIndex)
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.fileNamePatternWidget,
                                         'setDisabled(bool)')
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.videoFileNameWidget,
                                         'setEnabled(bool)')
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.videoLengthSliderWidget,
                                         'setEnabled(bool)')
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.videoFormatWidget,
                                         'setEnabled(bool)')
        self.videoFormatWidget.connect("currentIndexChanged(int)",
                                       self.updateVideoFormat)

        self.updateVideoFormat(0)
        self.updateViewOptions()
Пример #10
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        # Instantiate and connect widgets ...

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

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

        # directory selection
        self.inputDirectoryButton = qt.QPushButton("Select a Directory")
        self.inputDirectory = None
        parametersFormLayout.addRow("DICOM Input:", self.inputDirectoryButton)

        # phantom type selection
        self.phantomModelSelector = qt.QGroupBox()

        vbox = qt.QVBoxLayout()
        self.phantom_radios = []
        for name in sorted(phantom_definitions.PHANTOM_CATALOG.keys()):
            rb = qt.QRadioButton(name)
            self.phantom_radios.append(rb)
            vbox.addWidget(rb)
        self.phantomModelSelector.setLayout(vbox)
        parametersFormLayout.addRow("Select phantom model: ",
                                    self.phantomModelSelector)

        #
        # output DWI volume selector
        #
        self.outputDWISelector = slicer.qMRMLNodeComboBox()
        self.outputDWISelector.nodeTypes = [
            "vtkMRMLDiffusionWeightedVolumeNode"
        ]
        self.outputDWISelector.selectNodeUponCreation = True
        self.outputDWISelector.addEnabled = True
        self.outputDWISelector.removeEnabled = True
        self.outputDWISelector.renameEnabled = True
        self.outputDWISelector.noneEnabled = False
        self.outputDWISelector.showHidden = False
        self.outputDWISelector.showChildNodeTypes = False
        self.outputDWISelector.setMRMLScene(slicer.mrmlScene)
        self.outputDWISelector.setToolTip("Pick the output to the algorithm.")
        parametersFormLayout.addRow("Output DWI Volume: ",
                                    self.outputDWISelector)

        #
        # output scalar volume selector
        #
        self.outputSelector = slicer.qMRMLNodeComboBox()
        self.outputSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
        self.outputSelector.selectNodeUponCreation = True
        self.outputSelector.addEnabled = True
        self.outputSelector.removeEnabled = True
        self.outputSelector.renameEnabled = True
        self.outputSelector.noneEnabled = False
        self.outputSelector.showHidden = False
        self.outputSelector.showChildNodeTypes = False
        self.outputSelector.setMRMLScene(slicer.mrmlScene)
        self.outputSelector.setToolTip("Pick the output to the algorithm.")
        parametersFormLayout.addRow("Output Scalar Volume: ",
                                    self.outputSelector)

        #
        # output VOI selector
        #
        self.outputVOISelector = slicer.qMRMLNodeComboBox()
        self.outputVOISelector.nodeTypes = ["vtkMRMLLabelMapVolumeNode"]
        self.outputVOISelector.selectNodeUponCreation = True
        self.outputVOISelector.addEnabled = True
        self.outputVOISelector.removeEnabled = True
        self.outputVOISelector.renameEnabled = True
        self.outputVOISelector.noneEnabled = False
        self.outputVOISelector.showHidden = False
        self.outputVOISelector.showChildNodeTypes = False
        self.outputVOISelector.setMRMLScene(slicer.mrmlScene)
        self.outputVOISelector.setToolTip(
            "Pick the output VOI to the algorithm.")
        parametersFormLayout.addRow("Output VOI: ", self.outputVOISelector)

        #
        # Apply Button
        #
        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.toolTip = "Run the algorithm."
        self.applyButton.enabled = False
        parametersFormLayout.addRow(self.applyButton)

        # connections
        self.applyButton.connect('clicked(bool)', self.onApplyButton)
        self.inputDirectoryButton.connect('clicked(bool)',
                                          self.onInputDirectory)
        self.phantomModelSelector.connect('clicked(bool)', self.onSelect)
        self.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                    self.onSelect)
        self.outputDWISelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                       self.onSelect)
        self.outputVOISelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                       self.onSelect)

        # Refresh Apply button state
        self.onSelect()

        # Add space to display feedback from program
        self.statusLabel = qt.QPlainTextEdit()
        self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
        parametersFormLayout.addRow(self.statusLabel)

        # Add vertical spacer
        self.layout.addStretch(1)
Пример #11
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        # Instantiate and connect widgets ...

        self.registrationInProgress = False
        self.logic = SequenceRegistrationLogic()
        self.logic.logCallback = self.addLog

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

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

        #
        # input volume selector
        #
        self.inputSelector = slicer.qMRMLNodeComboBox()
        self.inputSelector.nodeTypes = ["vtkMRMLSequenceNode"]
        self.inputSelector.selectNodeUponCreation = True
        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 input volume sequence. Each time point will be registered to the fixed frame."
        )
        parametersFormLayout.addRow("Input volume sequence:",
                                    self.inputSelector)

        #
        # output volume selector
        #
        self.outputVolumesSelector = slicer.qMRMLNodeComboBox()
        self.outputVolumesSelector.nodeTypes = ["vtkMRMLSequenceNode"]
        self.outputVolumesSelector.baseName = "OutputVolumes"
        self.outputVolumesSelector.selectNodeUponCreation = True
        self.outputVolumesSelector.addEnabled = True
        self.outputVolumesSelector.removeEnabled = True
        self.outputVolumesSelector.renameEnabled = True
        self.outputVolumesSelector.noneEnabled = True
        self.outputVolumesSelector.showHidden = False
        self.outputVolumesSelector.showChildNodeTypes = False
        self.outputVolumesSelector.setMRMLScene(slicer.mrmlScene)
        self.outputVolumesSelector.setToolTip(
            "Select a node for storing computed motion-compensated volume sequence."
        )
        parametersFormLayout.addRow("Output volume sequence:",
                                    self.outputVolumesSelector)

        #
        # output transform selector
        #
        self.outputTransformSelector = slicer.qMRMLNodeComboBox()
        self.outputTransformSelector.nodeTypes = ["vtkMRMLSequenceNode"]
        self.outputTransformSelector.baseName = "OutputTransforms"
        self.outputTransformSelector.selectNodeUponCreation = True
        self.outputTransformSelector.addEnabled = True
        self.outputTransformSelector.removeEnabled = True
        self.outputTransformSelector.renameEnabled = True
        self.outputTransformSelector.noneEnabled = True
        self.outputTransformSelector.showHidden = False
        self.outputTransformSelector.showChildNodeTypes = False
        self.outputTransformSelector.setMRMLScene(slicer.mrmlScene)
        self.outputTransformSelector.setToolTip(
            "Computed displacement field that transform nodes from moving volume space to fixed volume space. NOTE: You must set at least one output sequence (transform and/or volume)."
        )
        parametersFormLayout.addRow("Output transform sequence:",
                                    self.outputTransformSelector)

        #
        # Output transform mode
        #
        import Elastix
        self.registrationPresetSelector = qt.QComboBox()
        self.registrationPresetSelector.setToolTip(
            "Pick preset to register with.")
        for preset in self.logic.elastixLogic.getRegistrationPresets():
            self.registrationPresetSelector.addItem("{0} ({1})".format(
                preset[Elastix.RegistrationPresets_Modality],
                preset[Elastix.RegistrationPresets_Content]))
        self.registrationPresetSelector.addItem("*NEW*")
        self.newPresetIndex = self.registrationPresetSelector.count - 1
        parametersFormLayout.addRow("Preset:", self.registrationPresetSelector)

        #
        # Advanced Area
        #
        advancedCollapsibleButton = ctk.ctkCollapsibleButton()
        advancedCollapsibleButton.text = "Advanced"
        advancedCollapsibleButton.collapsed = 1
        self.layout.addWidget(advancedCollapsibleButton)

        # Layout within the dummy collapsible button
        advancedFormLayout = qt.QFormLayout(advancedCollapsibleButton)

        # Fixed frame index
        self.sequenceFixedItemIndexWidget = ctk.ctkSliderWidget()
        self.sequenceFixedItemIndexWidget.decimals = 0
        self.sequenceFixedItemIndexWidget.singleStep = 1
        self.sequenceFixedItemIndexWidget.minimum = 0
        self.sequenceFixedItemIndexWidget.value = 0
        self.sequenceFixedItemIndexWidget.setToolTip(
            "Set the frame of the input sequence to use as the fixed volume (that all other volumes will be registered to."
        )
        advancedFormLayout.addRow("Fixed frame index:",
                                  self.sequenceFixedItemIndexWidget)

        # Sequence start index
        self.sequenceStartItemIndexWidget = ctk.ctkSliderWidget()
        self.sequenceStartItemIndexWidget.minimum = 0
        self.sequenceStartItemIndexWidget.decimals = 0
        self.sequenceStartItemIndexWidget.setToolTip(
            "First item in the sequence to register.")
        advancedFormLayout.addRow("Start frame index:",
                                  self.sequenceStartItemIndexWidget)

        # Sequence end index
        self.sequenceEndItemIndexWidget = ctk.ctkSliderWidget()
        self.sequenceEndItemIndexWidget.minimum = 0
        self.sequenceEndItemIndexWidget.decimals = 0
        self.sequenceEndItemIndexWidget.setToolTip(
            "Last item in the sequence to register.")
        advancedFormLayout.addRow("End frame index:",
                                  self.sequenceEndItemIndexWidget)

        #
        # Transform direction
        #
        self.transformDirectionSelector = qt.QComboBox()
        self.transformDirectionSelector.setToolTip(
            "Moving to fixed: computes stabilizing transform. Fixed to moving: computes morphing transform, which deforms structures defined on the fixed frame to all moving frames."
        )
        self.transformDirectionSelector.addItem("moving frames to fixed frame")
        self.transformDirectionSelector.addItem("fixed frame to moving frames")
        advancedFormLayout.addRow("Transform direction:",
                                  self.transformDirectionSelector)

        #
        # Option to show detailed log
        #

        self.showDetailedLogDuringExecutionCheckBox = qt.QCheckBox(" ")
        self.showDetailedLogDuringExecutionCheckBox.checked = False
        label = qt.QLabel("Show detailed log during registration:")
        label.setToolTip("Show detailed log during registration.")
        self.showDetailedLogDuringExecutionCheckBox.setToolTip(
            "Show detailed log during registration.")
        advancedFormLayout.addRow(label,
                                  self.showDetailedLogDuringExecutionCheckBox)

        #
        # Option to keep temporary files after registration
        #

        self.keepTemporaryFilesCheckBox = qt.QCheckBox(" ")
        self.keepTemporaryFilesCheckBox.checked = False
        label = qt.QLabel("Keep temporary files:")
        label.setToolTip(
            "Keep temporary files (inputs, computed outputs, logs) after the registration is completed."
        )
        self.keepTemporaryFilesCheckBox.setToolTip(
            "Keep temporary files (inputs, computed outputs, logs) after the registration is completed."
        )

        #
        # Button to open the folder in which temporary files are stored
        #

        self.showTemporaryFilesFolderButton = qt.QPushButton(
            "Show temp folder")
        self.showTemporaryFilesFolderButton.toolTip = "Open the folder where temporary files are stored."
        self.showTemporaryFilesFolderButton.setSizePolicy(
            qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred)

        hbox = qt.QHBoxLayout()
        hbox.addWidget(self.keepTemporaryFilesCheckBox)
        hbox.addWidget(self.showTemporaryFilesFolderButton)
        advancedFormLayout.addRow(label, hbox)

        self.showRegistrationParametersDatabaseFolderButton = qt.QPushButton(
            "Show database folder")
        self.showRegistrationParametersDatabaseFolderButton.toolTip = "Open the folder where temporary files are stored."
        self.showRegistrationParametersDatabaseFolderButton.setSizePolicy(
            qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred)
        advancedFormLayout.addRow(
            "Registration presets:",
            self.showRegistrationParametersDatabaseFolderButton)

        customElastixBinDir = self.logic.elastixLogic.getCustomElastixBinDir()
        self.customElastixBinDirSelector = ctk.ctkPathLineEdit()
        self.customElastixBinDirSelector.filters = ctk.ctkPathLineEdit.Dirs
        self.customElastixBinDirSelector.setCurrentPath(customElastixBinDir)
        self.customElastixBinDirSelector.setSizePolicy(
            qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred)
        self.customElastixBinDirSelector.setToolTip(
            "Set bin directory of an Elastix installation (where elastix executable is located). "
            "If value is empty then default elastix (bundled with SlicerElastix extension) will be used."
        )
        advancedFormLayout.addRow("Custom Elastix toolbox location:",
                                  self.customElastixBinDirSelector)

        #
        # Apply Button
        #
        self.applyButton = qt.QPushButton("Register")
        self.applyButton.toolTip = "Start registration."
        self.applyButton.enabled = False
        self.layout.addWidget(self.applyButton)

        self.statusLabel = qt.QPlainTextEdit()
        self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
        self.statusLabel.setCenterOnScroll(True)
        self.layout.addWidget(self.statusLabel)

        # connections
        self.applyButton.connect('clicked(bool)', self.onApplyButton)
        self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                   self.onInputSelect)
        self.outputVolumesSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                           self.onSelect)
        self.outputTransformSelector.connect(
            "currentNodeChanged(vtkMRMLNode*)", self.onSelect)
        self.sequenceFixedItemIndexWidget.connect('valueChanged(double)',
                                                  self.setSequenceItemIndex)
        self.sequenceStartItemIndexWidget.connect('valueChanged(double)',
                                                  self.setSequenceItemIndex)
        self.sequenceEndItemIndexWidget.connect('valueChanged(double)',
                                                self.setSequenceItemIndex)
        self.showTemporaryFilesFolderButton.connect(
            'clicked(bool)', self.onShowTemporaryFilesFolder)
        self.showRegistrationParametersDatabaseFolderButton.connect(
            'clicked(bool)', self.onShowRegistrationParametersDatabaseFolder)
        # Immediately update deleteTemporaryFiles and show detailed logs in the logic to make it possible to decide to
        # update these variables while the registration is running
        self.keepTemporaryFilesCheckBox.connect(
            "toggled(bool)", self.onKeepTemporaryFilesToggled)
        self.showDetailedLogDuringExecutionCheckBox.connect(
            "toggled(bool)", self.onShowLogToggled)
        # Check if user selects to create a new preset
        self.registrationPresetSelector.connect("activated(int)",
                                                self.onCreatePresetPressed)

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

        # Variable initializations
        self.newParameterButtons = []

        # Refresh Apply button state
        self.onInputSelect()
Пример #12
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        self.logic = ScreenCaptureLogic()
        self.logic.logCallback = self.addLog

        # Instantiate and connect widgets ...

        #
        # Input area
        #
        inputCollapsibleButton = ctk.ctkCollapsibleButton()
        inputCollapsibleButton.text = "Input"
        self.layout.addWidget(inputCollapsibleButton)
        inputFormLayout = qt.QFormLayout(inputCollapsibleButton)

        # Input view selector
        self.viewNodeSelector = slicer.qMRMLNodeComboBox()
        self.viewNodeSelector.nodeTypes = [
            "vtkMRMLSliceNode", "vtkMRMLViewNode"
        ]
        self.viewNodeSelector.addEnabled = False
        self.viewNodeSelector.removeEnabled = False
        self.viewNodeSelector.noneEnabled = False
        self.viewNodeSelector.showHidden = False
        self.viewNodeSelector.showChildNodeTypes = False
        self.viewNodeSelector.setMRMLScene(slicer.mrmlScene)
        self.viewNodeSelector.setToolTip(
            "Contents of this slice or 3D view will be captured.")
        inputFormLayout.addRow("View to capture: ", self.viewNodeSelector)

        #
        # Slice view options area
        #
        self.sliceViewOptionsCollapsibleButton = ctk.ctkCollapsibleButton()
        self.sliceViewOptionsCollapsibleButton.text = "Slice viewer sweep"
        self.layout.addWidget(self.sliceViewOptionsCollapsibleButton)
        sliceViewOptionsLayout = qt.QFormLayout(
            self.sliceViewOptionsCollapsibleButton)

        # Start slice offset position
        self.startSliceOffsetSliderWidget = ctk.ctkSliderWidget()
        self.startSliceOffsetSliderWidget.singleStep = 30
        self.startSliceOffsetSliderWidget.minimum = -100
        self.startSliceOffsetSliderWidget.maximum = 100
        self.startSliceOffsetSliderWidget.value = 0
        self.startSliceOffsetSliderWidget.setToolTip("Start slice offset.")
        sliceViewOptionsLayout.addRow("Start offset:",
                                      self.startSliceOffsetSliderWidget)

        # End slice offset position
        self.endSliceOffsetSliderWidget = ctk.ctkSliderWidget()
        self.endSliceOffsetSliderWidget.singleStep = 5
        self.endSliceOffsetSliderWidget.minimum = -100
        self.endSliceOffsetSliderWidget.maximum = 100
        self.endSliceOffsetSliderWidget.value = 0
        self.endSliceOffsetSliderWidget.setToolTip("End slice offset.")
        sliceViewOptionsLayout.addRow("End offset:",
                                      self.endSliceOffsetSliderWidget)

        #
        # 3D view options area
        #
        self.threeDViewOptionsCollapsibleButton = ctk.ctkCollapsibleButton()
        self.threeDViewOptionsCollapsibleButton.text = "3D view rotation"
        self.layout.addWidget(self.threeDViewOptionsCollapsibleButton)
        threeDViewOptionsLayout = qt.QFormLayout(
            self.threeDViewOptionsCollapsibleButton)

        # Start rotation
        self.startRotationSliderWidget = ctk.ctkSliderWidget()
        self.startRotationSliderWidget.singleStep = 5
        self.startRotationSliderWidget.minimum = 0
        self.startRotationSliderWidget.maximum = 180
        self.startRotationSliderWidget.value = 180
        self.startRotationSliderWidget.setToolTip(
            "Rotation angle for the first image, relative to current orientation."
        )
        threeDViewOptionsLayout.addRow("Start rotation angle:",
                                       self.startRotationSliderWidget)

        # End rotation
        self.endRotationSliderWidget = ctk.ctkSliderWidget()
        self.endRotationSliderWidget.singleStep = 5
        self.endRotationSliderWidget.minimum = 0
        self.endRotationSliderWidget.maximum = 180
        self.endRotationSliderWidget.value = 180
        self.endRotationSliderWidget.setToolTip(
            "Rotation angle for the last image, relative to current orientation."
        )
        threeDViewOptionsLayout.addRow("End rotation angle:",
                                       self.endRotationSliderWidget)

        #
        # Output area
        #
        outputCollapsibleButton = ctk.ctkCollapsibleButton()
        outputCollapsibleButton.text = "Output"
        self.layout.addWidget(outputCollapsibleButton)
        outputFormLayout = qt.QFormLayout(outputCollapsibleButton)

        # Number of steps value
        self.numberOfStepsSliderWidget = ctk.ctkSliderWidget()
        self.numberOfStepsSliderWidget.singleStep = 5
        self.numberOfStepsSliderWidget.minimum = 2
        self.numberOfStepsSliderWidget.maximum = 150
        self.numberOfStepsSliderWidget.value = 30
        self.numberOfStepsSliderWidget.decimals = 0
        self.numberOfStepsSliderWidget.setToolTip(
            "Number of images extracted between start and stop positions.")
        outputFormLayout.addRow("Number of images:",
                                self.numberOfStepsSliderWidget)

        # Output directory selector
        self.outputDirSelector = ctk.ctkPathLineEdit()
        self.outputDirSelector.filters = ctk.ctkPathLineEdit.Dirs
        self.outputDirSelector.settingKey = 'ScreenCaptureOutputDir'
        outputFormLayout.addRow("Output directory:", self.outputDirSelector)
        if not self.outputDirSelector.currentPath:
            defaultOutputPath = os.path.abspath(
                os.path.join(slicer.app.defaultScenePath, 'SlicerCapture'))
            self.outputDirSelector.setCurrentPath(defaultOutputPath)

        self.videoExportCheckBox = qt.QCheckBox()
        self.videoExportCheckBox.checked = False
        self.videoExportCheckBox.setToolTip(
            "If checked, exported images will be written as a video file.")
        outputFormLayout.addRow("Video export:", self.videoExportCheckBox)

        self.videoFileNameWidget = qt.QLineEdit()
        self.videoFileNameWidget.setToolTip(
            "String that defines file name, type, and numbering scheme. Default: capture.avi."
        )
        self.videoFileNameWidget.text = "SlicerCapture.avi"
        self.videoFileNameWidget.setEnabled(False)
        outputFormLayout.addRow("Video file name:", self.videoFileNameWidget)

        self.videoQualitySliderWidget = ctk.ctkSliderWidget()
        self.videoQualitySliderWidget.singleStep = 0.1
        self.videoQualitySliderWidget.minimum = 0
        self.videoQualitySliderWidget.maximum = 20
        self.videoQualitySliderWidget.value = 2
        self.videoQualitySliderWidget.decimals = 1
        self.videoQualitySliderWidget.setToolTip(
            "Bit-rate of video. Higher value means higher quality and larger file size."
        )
        outputFormLayout.addRow("Video quality:",
                                self.videoQualitySliderWidget)

        self.videoFrameRateSliderWidget = ctk.ctkSliderWidget()
        self.videoFrameRateSliderWidget.singleStep = 0.1
        self.videoFrameRateSliderWidget.minimum = 0.1
        self.videoFrameRateSliderWidget.maximum = 60
        self.videoFrameRateSliderWidget.value = 25
        self.videoFrameRateSliderWidget.decimals = 0
        self.videoFrameRateSliderWidget.setToolTip(
            "Frames per second. Higher values mean faster, shorter videos.")
        outputFormLayout.addRow("Frame rate:", self.videoFrameRateSliderWidget)

        # Capture button
        self.captureButton = qt.QPushButton("Capture")
        self.captureButton.toolTip = "Capture slice sweep to image sequence."
        outputFormLayout.addRow(self.captureButton)

        self.statusLabel = qt.QPlainTextEdit()
        self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
        self.statusLabel.setCenterOnScroll(True)
        outputFormLayout.addRow(self.statusLabel)

        #
        # Advanced area
        #
        self.advancedCollapsibleButton = ctk.ctkCollapsibleButton()
        self.advancedCollapsibleButton.text = "Advanced"
        self.advancedCollapsibleButton.collapsed = (self.logic.getFfmpegPath()
                                                    is not None)
        self.layout.addWidget(self.advancedCollapsibleButton)
        advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton)

        self.fileNamePatternWidget = qt.QLineEdit()
        self.fileNamePatternWidget.setToolTip(
            "String that defines file name, type, and numbering scheme. Default: image%05d.png."
        )
        self.fileNamePatternWidget.text = "image_%05d.png"
        advancedFormLayout.addRow("Image file name pattern:",
                                  self.fileNamePatternWidget)

        ffmpegPath = self.logic.getFfmpegPath()
        self.ffmpegPathSelector = ctk.ctkPathLineEdit()
        self.ffmpegPathSelector.setCurrentPath(ffmpegPath)
        self.ffmpegPathSelector.nameFilters = ['ffmpeg.exe', 'ffmpeg']
        self.ffmpegPathSelector.setMaximumWidth(300)
        self.ffmpegPathSelector.setToolTip(
            "Set the path to ffmpeg executable. Download from: https://www.ffmpeg.org/"
        )
        self.ffmpegPathSelector.setEnabled(False)
        advancedFormLayout.addRow("ffmpeg executable:",
                                  self.ffmpegPathSelector)

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

        # connections
        self.captureButton.connect('clicked(bool)', self.onCaptureButton)
        self.viewNodeSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                      self.onViewNodeSelected)
        self.startSliceOffsetSliderWidget.connect('valueChanged(double)',
                                                  self.setSliceOffset)
        self.endSliceOffsetSliderWidget.connect('valueChanged(double)',
                                                self.setSliceOffset)
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.fileNamePatternWidget,
                                         'setDisabled(bool)')
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.ffmpegPathSelector,
                                         'setEnabled(bool)')
        self.videoExportCheckBox.connect('toggled(bool)',
                                         self.videoFileNameWidget,
                                         'setEnabled(bool)')

        self.onViewNodeSelected()
Пример #13
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        # Instantiate and connect widgets ...

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

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

        #
        # input volume selector
        #
        self.inputSelector = slicer.qMRMLNodeComboBox()
        self.inputSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
        self.inputSelector.selectNodeUponCreation = True
        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("Input Volume: ", self.inputSelector)

        #
        # iterations value
        #
        self.iterationsSliderWidget = ctk.ctkSliderWidget()
        self.iterationsSliderWidget.singleStep = 1
        self.iterationsSliderWidget.minimum = 1
        self.iterationsSliderWidget.maximum = 200
        self.iterationsSliderWidget.value = 20
        self.iterationsSliderWidget.setToolTip(
            """Number of iterations to run.""")
        parametersFormLayout.addRow("Iterations", self.iterationsSliderWidget)

        #
        # smoothing value
        #
        self.smoothingSliderWidget = ctk.ctkSliderWidget()
        self.smoothingSliderWidget.singleStep = 1
        self.smoothingSliderWidget.minimum = 1
        self.smoothingSliderWidget.maximum = 4
        self.smoothingSliderWidget.value = 1
        self.smoothingSliderWidget.setToolTip(
            """Number of times the smoothing operator is applied per iteration.
            Larger values lead to smoother segmentations.""")
        parametersFormLayout.addRow("Smoothing", self.smoothingSliderWidget)

        #
        # threshold value
        #
        self.thresholdSliderWidget = ctk.ctkSliderWidget()
        self.thresholdSliderWidget.singleStep = 0.01
        self.thresholdSliderWidget.minimum = 0
        self.thresholdSliderWidget.maximum = 1
        self.thresholdSliderWidget.value = 0.5
        self.thresholdSliderWidget.setToolTip(
            """Areas of the image with a value smaller than this threshold will be
                                               considered borders. The evolution of the contour will stop in this
                                               areas.""")
        parametersFormLayout.addRow("Threshold (GAC only)",
                                    self.thresholdSliderWidget)

        #
        # check box to trigger taking screen shots for later use in tutorials
        #
        self.enableBaloonFlagCheckBox = qt.QCheckBox()
        self.enableBaloonFlagCheckBox.checked = 1
        self.enableBaloonFlagCheckBox.setToolTip(
            """Balloon force to guide the contour in non-informative areas of the
                                                  image, i.e., areas where the gradient of the image is too small to push
                                                  the contour towards a border. A negative value will shrink the contour,
                                                  while a positive value will expand the contour in these areas."""
        )
        parametersFormLayout.addRow("Baloon (GAC only)",
                                    self.enableBaloonFlagCheckBox)

        self.markupsNode = slicer.mrmlScene.AddNewNodeByClass(
            "vtkMRMLMarkupsFiducialNode")

        self.placeWidget = slicer.qSlicerMarkupsPlaceWidget()
        self.placeWidget.setMRMLScene(slicer.mrmlScene)
        self.placeWidget.setCurrentNode(self.markupsNode)
        self.placeWidget.buttonsVisible = False
        self.placeWidget.placeButton().show()
        self.placeWidget.connect('activeMarkupsFiducialPlaceModeChanged(bool)',
                                 self.placementModeChanged)
        parametersFormLayout.addRow(self.placeWidget)

        #
        # name value
        #
        self.textWidget = qt.QPlainTextEdit("Tumor")
        parametersFormLayout.addRow("Segment name", self.textWidget)

        #
        # color value
        #
        self.color = [255, 255, 0]
        self.colorWidget = qt.QColorDialog()
        self.colorWidget.setOption(2)
        self.colorWidget.setCurrentColor(
            qt.QColor(self.color[0], self.color[1], self.color[2]))
        self.colorWidget.connect('currentColorChanged(QColor)',
                                 self.colorChanged)
        parametersFormLayout.addRow("Select color", self.colorWidget)

        #
        # 3D - MorphACWE Button
        #
        self.acwe3d = qt.QPushButton("3D - MorphACWE")
        self.acwe3d.toolTip = "Run the algorithm."
        self.acwe3d.enabled = True
        self.acwe3d.connect('clicked(bool)', self.onAcwe3d)
        parametersFormLayout.addRow(self.acwe3d)
        #
        # 2D - MorphACWE Button
        #
        self.acwe2d = qt.QPushButton("2D - MorphACWE")
        self.acwe2d.toolTip = "Run the algorithm."
        self.acwe2d.enabled = True
        self.acwe2d.connect('clicked(bool)', self.onAcwe2d)
        parametersFormLayout.addRow(self.acwe2d)

        #
        # 2D - MorphACWE Prev Button
        #
        self.acwe_prev2d = qt.QPushButton("2D - MorphACWE (prev)")
        self.acwe_prev2d.toolTip = "Run the algorithm."
        self.acwe_prev2d.enabled = True
        self.acwe_prev2d.connect('clicked(bool)', self.onAcwe2dPrev)
        parametersFormLayout.addRow(self.acwe_prev2d)

        #
        # 3D - MorphGAC Button
        #
        self.gac3d = qt.QPushButton("3D - MorphGAC")
        self.gac3d.toolTip = "Run the algorithm."
        self.gac3d.enabled = True
        self.gac3d.connect('clicked(bool)', self.onGac3d)
        parametersFormLayout.addRow(self.gac3d)

        #
        # 2D - MorphGAC Button
        #
        self.gac2d = qt.QPushButton("2D - MorphGAC")
        self.gac2d.toolTip = "Run the algorithm."
        self.gac2d.enabled = True
        self.gac2d.connect('clicked(bool)', self.onGac2d)
        parametersFormLayout.addRow(self.gac2d)

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

        self.ras = [0, 0, 0]