Example #1
1
  def setup(self):
    ScriptedLoadableModuleWidget.setup(self)

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

    self.snapshotIndex = 0 # this counter is used for determining file names for single-image snapshots
    self.snapshotOutputDir = None
    self.snapshotFileNamePattern = None

    # Instantiate and connect widgets ...

    #
    # Input area
    #
    self.inputCollapsibleButton = ctk.ctkCollapsibleButton()
    self.inputCollapsibleButton.text = "Input"
    self.layout.addWidget(self.inputCollapsibleButton)
    inputFormLayout = qt.QFormLayout(self.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("This slice or 3D view will be updated during capture."
      "Only this view will be captured unless 'Capture of all views' option in output section is enabled." )
    inputFormLayout.addRow("Master view: ", 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 rotation range
    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)

    # 3D rotation axis
    self.rotationAxisLabel = qt.QLabel("Rotation axis:")
    self.rotationAxisWidget = ctk.ctkRangeWidget()
    self.rotationAxisWidget = qt.QComboBox()
    self.rotationAxisWidget.addItem("Yaw", AXIS_YAW)
    self.rotationAxisWidget.addItem("Pitch", AXIS_PITCH)
    inputFormLayout.addRow(self.rotationAxisLabel, self.rotationAxisWidget)


    # 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
    #
    self.outputCollapsibleButton = ctk.ctkCollapsibleButton()
    self.outputCollapsibleButton.text = "Output"
    self.layout.addWidget(self.outputCollapsibleButton)
    outputFormLayout = qt.QFormLayout(self.outputCollapsibleButton)

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

    # Single step toggle button
    self.singleStepButton = qt.QToolButton()
    self.singleStepButton.setText("single")
    self.singleStepButton.setCheckable(True)
    self.singleStepButton.toolTip = "Capture a single image of current state only.\n" + \
      "New filename is generated for each captured image (no files are overwritten)."

    hbox = qt.QHBoxLayout()
    hbox.addWidget(self.singleStepButton)
    hbox.addWidget(self.numberOfStepsSliderWidget)
    outputFormLayout.addRow("Number of images:", hbox)

    # 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.captureAllViewsCheckBox = qt.QCheckBox(" ")
    self.captureAllViewsCheckBox.checked = False
    self.captureAllViewsCheckBox.setToolTip("If checked, all views will be captured. If unchecked then only the selected view will be captured.")
    outputFormLayout.addRow("Capture all views:", self.captureAllViewsCheckBox)

    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 (without backward steps and repeating).")
    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.forwardBackwardCheckBox = qt.QCheckBox(" ")
    self.forwardBackwardCheckBox.checked = False
    self.forwardBackwardCheckBox.setToolTip("If checked, image series will be generated playing forward and then backward.")
    advancedFormLayout.addRow("Forward-backward:", self.forwardBackwardCheckBox)

    self.repeatSliderWidget = ctk.ctkSliderWidget()
    self.repeatSliderWidget.decimals = 0
    self.repeatSliderWidget.singleStep = 1
    self.repeatSliderWidget.minimum = 1
    self.repeatSliderWidget.maximum = 50
    self.repeatSliderWidget.value = 1
    self.repeatSliderWidget.setToolTip("Number of times image series are repeated. Useful for making short videos longer for playback in software"
      " that does not support looped playback.")
    advancedFormLayout.addRow("Repeat:", self.repeatSliderWidget)

    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)

    self.maxFramesWidget = qt.QSpinBox()
    self.maxFramesWidget.setRange(1, 9999)
    self.maxFramesWidget.setValue(600)
    self.maxFramesWidget.setToolTip(
      "Maximum number of images to be captured (without backward steps and repeating).")
    advancedFormLayout.addRow("Maximum number of images:", self.maxFramesWidget)

    # Capture button
    self.captureButtonLabelCapture = "Capture"
    self.captureButtonLabelCancel = "Cancel"
    self.captureButton = qt.QPushButton(self.captureButtonLabelCapture)
    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)
    self.layout.addLayout(hbox)

    self.statusLabel = qt.QPlainTextEdit()
    self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse)
    self.statusLabel.setCenterOnScroll(True)
    self.layout.addWidget(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.singleStepButton.connect('toggled(bool)', self.numberOfStepsSliderWidget, 'setDisabled(bool)')
    self.maxFramesWidget.connect('valueChanged(int)', self.maxFramesChanged)

    self.updateVideoFormat(0)
    self.updateViewOptions()
    def setupOptionsFrame(self):
        self.thresholdSliderLabel = qt.QLabel("Threshold Range:")
        self.thresholdSliderLabel.setToolTip(
            "Set the range of the background values that should be labeled.")
        self.scriptedEffect.addOptionsWidget(self.thresholdSliderLabel)

        self.thresholdSlider = ctk.ctkRangeWidget()
        self.thresholdSlider.spinBoxAlignment = qt.Qt.AlignTop
        self.thresholdSlider.singleStep = 0.01
        self.scriptedEffect.addOptionsWidget(self.thresholdSlider)

        self.useForPaintButton = qt.QPushButton("Use For Paint")
        self.useForPaintButton.setToolTip(
            "Transfer the current threshold settings to be used for labeling operations such as Paint and Draw."
        )
        self.scriptedEffect.addOptionsWidget(self.useForPaintButton)

        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.objectName = self.__class__.__name__ + 'Apply'
        self.applyButton.setToolTip(
            "Apply current threshold settings to the label map.")
        self.scriptedEffect.addOptionsWidget(self.applyButton)

        self.useForPaintButton.connect('clicked()', self.onUseForPaint)
        self.thresholdSlider.connect('valuesChanged(double,double)',
                                     self.onThresholdValuesChanged)
        self.applyButton.connect('clicked()', self.onApply)
Example #3
0
  def create(self):
    super().create()
    self.paintOver = qt.QCheckBox("Paint Over", self.frame)
    self.paintOver.setToolTip("Allow effect to overwrite non-zero labels.")
    self.frame.layout().addWidget(self.paintOver)
    self.widgets.append(self.paintOver)

    self.thresholdPaint = qt.QCheckBox("Threshold Paint", self.frame)
    self.thresholdPaint.setToolTip("Enable/Disable threshold mode for labeling.")
    self.frame.layout().addWidget(self.thresholdPaint)
    self.widgets.append(self.thresholdPaint)

    self.thresholdLabel = qt.QLabel("Threshold", self.frame)
    self.thresholdLabel.setToolTip("In threshold mode, the label will only be set if the background value is within this range.")
    self.frame.layout().addWidget(self.thresholdLabel)
    self.widgets.append(self.thresholdLabel)
    self.threshold = ctk.ctkRangeWidget(self.frame)
    self.threshold.spinBoxAlignment = 0xff # put enties on top
    self.threshold.singleStep = 0.01
    self.setRangeWidgetToBackgroundRange(self.threshold)
    self.frame.layout().addWidget(self.threshold)
    self.widgets.append(self.threshold)

    if not self.usesPaintOver:
      self.paintOver.hide()
    if not self.usesThreshold:
      self.thresholdPaint.hide()
      self.thresholdLabel.hide()
      self.threshold.hide()

    self.connections.append( (self.paintOver, "clicked()", self.updateMRMLFromGUI ) )
    self.connections.append( (self.thresholdPaint, "clicked()", self.updateMRMLFromGUI ) )
    self.connections.append( (self.threshold, "valuesChanged(double,double)", self.onThresholdValuesChange ) )
Example #4
0
  def create(self):
    super(LabelEffectOptions,self).create()
    self.paintOver = qt.QCheckBox("Paint Over", self.frame)
    self.paintOver.setToolTip("Allow effect to overwrite non-zero labels.")
    self.frame.layout().addWidget(self.paintOver)
    self.widgets.append(self.paintOver)

    self.thresholdPaint = qt.QCheckBox("Threshold Paint", self.frame)
    self.thresholdPaint.setToolTip("Enable/Disable threshold mode for labeling.")
    self.frame.layout().addWidget(self.thresholdPaint)
    self.widgets.append(self.thresholdPaint)

    self.thresholdLabel = qt.QLabel("Threshold", self.frame)
    self.thresholdLabel.setToolTip("In threshold mode, the label will only be set if the background value is within this range.")
    self.frame.layout().addWidget(self.thresholdLabel)
    self.widgets.append(self.thresholdLabel)
    self.threshold = ctk.ctkRangeWidget(self.frame)
    self.threshold.spinBoxAlignment = 0xff # put enties on top
    self.threshold.singleStep = 0.01
    self.setRangeWidgetToBackgroundRange(self.threshold)
    self.frame.layout().addWidget(self.threshold)
    self.widgets.append(self.threshold)

    if not self.usesPaintOver:
      self.paintOver.hide()
    if not self.usesThreshold:
      self.thresholdPaint.hide()
      self.thresholdLabel.hide()
      self.threshold.hide()

    self.connections.append( (self.paintOver, "clicked()", self.updateMRMLFromGUI ) )
    self.connections.append( (self.thresholdPaint, "clicked()", self.updateMRMLFromGUI ) )
    self.connections.append( (self.threshold, "valuesChanged(double,double)", self.onThresholdValuesChange ) )
Example #5
0
    def setupOptionsFrame(self):
        self.thresholdSliderLabel = qt.QLabel("Threshold Range:")
        self.thresholdSliderLabel.setToolTip(
            "Set the range of the background values that should be labeled.")
        self.scriptedEffect.addOptionsWidget(self.thresholdSliderLabel)

        self.thresholdSlider = ctk.ctkRangeWidget()
        self.thresholdSlider.spinBoxAlignment = qt.Qt.AlignTop
        self.thresholdSlider.singleStep = 0.01
        self.scriptedEffect.addOptionsWidget(self.thresholdSlider)

        self.useForPaintButton = qt.QPushButton("Use for masking")
        self.useForPaintButton.setToolTip(
            "Use specified intensity range for masking and switch to Paint effect."
        )
        self.scriptedEffect.addOptionsWidget(self.useForPaintButton)

        self.applyButton = qt.QPushButton("Apply")
        self.applyButton.objectName = self.__class__.__name__ + 'Apply'
        self.applyButton.setToolTip(
            "Fill selected segment in regions that are in the specified intensity range."
        )
        self.scriptedEffect.addOptionsWidget(self.applyButton)

        self.useForPaintButton.connect('clicked()', self.onUseForPaint)
        self.thresholdSlider.connect('valuesChanged(double,double)',
                                     self.onThresholdValuesChanged)
        self.applyButton.connect('clicked()', self.onApply)
Example #6
0
    def makeThresholdsWidgets(self):
        self.thresholdsTab = qt.QWidget()
        self.parametersTabWidget.addTab(self.thresholdsTab, 'Thresholds')
        self.thresholdsLayout = qt.QFormLayout(self.thresholdsTab)

        self.referenceThresholdSlider = ctk.ctkRangeWidget()
        self.referenceThresholdSlider.decimals = 0
        self.referenceThresholdSlider.valuesChanged.connect(
            self.onReferenceThresholdSlider)
        self.thresholdsLayout.addRow('Reference: ',
                                     self.referenceThresholdSlider)

        self.floatingThresholdSlider = ctk.ctkRangeWidget()
        self.floatingThresholdSlider.decimals = 0
        self.floatingThresholdSlider.valuesChanged.connect(
            self.onFloatingThresholdSlider)
        self.thresholdsLayout.addRow('Floating: ',
                                     self.floatingThresholdSlider)
Example #7
0
    def create(self):
        super().create()

        self.thresholdLabel = qt.QLabel("Threshold Range:", self.frame)
        self.thresholdLabel.setToolTip(
            "Set the range of the background values that should be labeled.")
        self.frame.layout().addWidget(self.thresholdLabel)
        self.widgets.append(self.thresholdLabel)
        self.threshold = ctk.ctkRangeWidget(self.frame)
        self.threshold.spinBoxAlignment = 0xff  # put enties on top
        self.threshold.singleStep = 0.01
        # set min/max based on current range
        success, lo, hi = self.getBackgroundScalarRange()
        if success:
            self.threshold.minimum, self.threshold.maximum = lo, hi
            self.threshold.singleStep = (hi - lo) / 1000.
        self.frame.layout().addWidget(self.threshold)
        self.widgets.append(self.threshold)

        self.useForPainting = qt.QPushButton("Use For Paint", self.frame)
        self.useForPainting.setToolTip(
            "Transfer the current threshold settings to be used for labeling operations such as Paint and Draw."
        )
        self.frame.layout().addWidget(self.useForPainting)
        self.widgets.append(self.useForPainting)

        self.apply = qt.QPushButton("Apply", self.frame)
        self.apply.objectName = self.__class__.__name__ + 'Apply'
        self.apply.setToolTip(
            "Apply current threshold settings to the label map.")
        self.frame.layout().addWidget(self.apply)
        self.widgets.append(self.apply)

        self.timer = qt.QTimer()
        self.previewState = 0
        self.previewStep = 1
        self.previewSteps = 5
        self.timer.start(200)

        self.connections.append((self.timer, 'timeout()', self.preview))
        self.connections.append(
            (self.useForPainting, 'clicked()', self.onUseForPainting))
        self.connections.append(
            (self.threshold, 'valuesChanged(double,double)',
             self.onThresholdValuesChanged))
        self.connections.append((self.apply, 'clicked()', self.onApply))

        HelpButton(
            self.frame,
            "Set labels based on threshold range.  Note: this replaces the current label map values."
        )

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Example #8
0
  def create(self):
    super(ThresholdEffectOptions,self).create()

    self.thresholdLabel = qt.QLabel("Threshold Range:", self.frame)
    self.thresholdLabel.setToolTip("Set the range of the background values that should be labeled.")
    self.frame.layout().addWidget(self.thresholdLabel)
    self.widgets.append(self.thresholdLabel)
    self.threshold = ctk.ctkRangeWidget(self.frame)
    self.threshold.spinBoxAlignment = 0xff # put enties on top
    self.threshold.singleStep = 0.01
    # set min/max based on current range
    success, lo, hi = self.getBackgroundScalarRange()
    if success:
      self.threshold.minimum, self.threshold.maximum = lo, hi
      self.threshold.singleStep = (hi - lo) / 1000.
    self.frame.layout().addWidget(self.threshold)
    self.widgets.append(self.threshold)

    self.useForPainting = qt.QPushButton("Use For Paint", self.frame)
    self.useForPainting.setToolTip("Transfer the current threshold settings to be used for labeling operations such as Paint and Draw.")
    self.frame.layout().addWidget(self.useForPainting)
    self.widgets.append(self.useForPainting)

    self.apply = qt.QPushButton("Apply", self.frame)
    self.apply.objectName = self.__class__.__name__ + 'Apply'
    self.apply.setToolTip("Apply current threshold settings to the label map.")
    self.frame.layout().addWidget(self.apply)
    self.widgets.append(self.apply)

    self.timer = qt.QTimer()
    self.previewState = 0
    self.previewStep = 1
    self.previewSteps = 5
    self.timer.start(200)

    self.connections.append( (self.timer, 'timeout()', self.preview) )
    self.connections.append( (self.useForPainting, 'clicked()', self.onUseForPainting) )
    self.connections.append( (self.threshold, 'valuesChanged(double,double)', self.onThresholdValuesChanged) )
    self.connections.append( (self.apply, 'clicked()', self.onApply) )

    HelpButton(self.frame, "Set labels based on threshold range.  Note: this replaces the current label map values.")

    # Add vertical spacer
    self.frame.layout().addStretch(1)
  def setupOptionsFrame(self):
    self.thresholdSliderLabel = qt.QLabel("Threshold Range:")
    self.thresholdSliderLabel.setToolTip("Set the range of the background values that should be labeled.")
    self.scriptedEffect.addOptionsWidget(self.thresholdSliderLabel)

    self.thresholdSlider = ctk.ctkRangeWidget()
    self.thresholdSlider.spinBoxAlignment = qt.Qt.AlignTop
    self.thresholdSlider.singleStep = 0.01
    self.scriptedEffect.addOptionsWidget(self.thresholdSlider)

    self.useForPaintButton = qt.QPushButton("Use For Paint")
    self.useForPaintButton.setToolTip("Transfer the current threshold settings to be used for labeling operations such as Paint and Draw.")
    self.scriptedEffect.addOptionsWidget(self.useForPaintButton)

    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.objectName = self.__class__.__name__ + 'Apply'
    self.applyButton.setToolTip("Apply current threshold settings to the label map.")
    self.scriptedEffect.addOptionsWidget(self.applyButton)

    self.useForPaintButton.connect('clicked()', self.onUseForPaint)
    self.thresholdSlider.connect('valuesChanged(double,double)', self.onThresholdValuesChanged)
    self.applyButton.connect('clicked()', self.onApply)
  def setupOptionsFrame(self):
    self.thresholdSliderLabel = qt.QLabel("Threshold Range:")
    self.thresholdSliderLabel.setToolTip("Set the range of the background values that should be labeled.")
    self.scriptedEffect.addOptionsWidget(self.thresholdSliderLabel)

    self.thresholdSlider = ctk.ctkRangeWidget()
    self.thresholdSlider.spinBoxAlignment = qt.Qt.AlignTop
    self.thresholdSlider.singleStep = 0.01
    self.scriptedEffect.addOptionsWidget(self.thresholdSlider)

    self.useForPaintButton = qt.QPushButton("Use for masking")
    self.useForPaintButton.setToolTip("Use specified intensity range for masking and switch to Paint effect.")
    self.scriptedEffect.addOptionsWidget(self.useForPaintButton)

    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.objectName = self.__class__.__name__ + 'Apply'
    self.applyButton.setToolTip("Fill selected segment in regions that are in the specified intensity range.")
    self.scriptedEffect.addOptionsWidget(self.applyButton)

    self.useForPaintButton.connect('clicked()', self.onUseForPaint)
    self.thresholdSlider.connect('valuesChanged(double,double)', self.onThresholdValuesChanged)
    self.applyButton.connect('clicked()', self.onApply)
Example #11
0
  def setup(self):
    self.developerMode = True
    ScriptedLoadableModuleWidget.setup(self)
    self.logic = RegistrationLogic()
    self.cropVolumeParameterNode = slicer.vtkMRMLCropVolumeParametersNode()
    
    # why initializing them here?
    
    self.VIEW_MODE_Preop_Only = 0 
    self.VIEW_MODE_Intraop_Only = 1
    self.VIEW_MODE_ThreeCompare = 2
    self.VIEW_MODE_Axial = 3
    self.VIEW_MODE_Sagittal = 4
    self.VIEW_MODE_Coronal = 5
    
    self.PREOP_VOLUME = None
    self.INTRAOP_VOLUME = None

    
    volumes = slicer.util.getNodesByClass("vtkMRMLScalarVolumeNode")
    for i in range(0,len(volumes)):
        if 'Preop' in volumes[i].GetName():
          self.PREOP_VOLUME = volumes[i]
        elif 'Intraop' in volumes[i].GetName():
          self.INTRAOP_VOLUME = volumes[i]
            
    
    
    scansCollapsibleButton = ctk.ctkCollapsibleButton()
    scansCollapsibleButton.text = "Volumes"
    
    self.layout.addWidget(scansCollapsibleButton)
    scansFormLayout = qt.QFormLayout(scansCollapsibleButton)
    # Layout within the dummy collapsible button
    
    
    # input inputBackVol
    self.inputBackVol = slicer.qMRMLNodeComboBox()
    self.inputBackVol.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.inputBackVol.selectNodeUponCreation = True
    self.inputBackVol.setAutoFillBackground(self.INTRAOP_VOLUME)
    self.inputBackVol.addEnabled = False
    self.inputBackVol.removeEnabled = False
    self.inputBackVol.noneEnabled = True
    self.inputBackVol.showHidden = False
    self.inputBackVol.showChildNodeTypes = False
    self.inputBackVol.setMRMLScene( slicer.mrmlScene )
    self.inputBackVol.setToolTip( "Pick the input scan to the algorithm." )
  #  self.layout.addWidget("Input Background Volume: ", self.inputBackVol)
    # input vol node connection
    self.inputBackVol.connect("currentNodeChanged(vtkMRMLNode*)", self.onInputBackVol)
    
    # input inputBackVol
    self.inputForVol = slicer.qMRMLNodeComboBox()
    self.inputForVol.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.inputForVol.selectNodeUponCreation = True
    self.inputForVol.setAutoFillBackground(self.PREOP_VOLUME)
    self.inputForVol.addEnabled = False
    self.inputForVol.removeEnabled = False
    self.inputForVol.noneEnabled = True
    self.inputForVol.showHidden = False
    self.inputForVol.showChildNodeTypes = False
    self.inputForVol.setMRMLScene( slicer.mrmlScene )
    self.inputForVol.setToolTip( "Pick the input scan to the algorithm." )
  #  self.layout.addWidget("Input Foreground Volume: ", self.inputForVol)
    # input vol node connection
    self.inputForVol.connect("currentNodeChanged(vtkMRMLNode*)", self.onInputForVol)   
    scansFormLayout.addRow("Input Intraop Volume: ", self.inputBackVol)
    scansFormLayout.addRow("Input Preop Volume: ", self.inputForVol)
    
    #  
    # ROI Area
    #
    self.roiCollapsibleGroupBox = ctk.ctkCollapsibleGroupBox()
    self.roiCollapsibleGroupBox.title = "Define ROI"
    self.roiCollapsibleGroupBox.collapsed = True
    self.layout.addWidget(self.roiCollapsibleGroupBox)

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

    # input intraop/fixed volume selector
    self.inputVol = slicer.qMRMLNodeComboBox()
    self.inputVol.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.inputVol.selectNodeUponCreation = True
    self.inputVol.setAutoFillBackground(False)
    self.inputVol.addEnabled = False
    self.inputVol.removeEnabled = False
    self.inputVol.noneEnabled = True
    self.inputVol.showHidden = False
    self.inputVol.showChildNodeTypes = False
    self.inputVol.setMRMLScene( slicer.mrmlScene )
    self.inputVol.setToolTip( "Pick the input scan to the algorithm." )
    roiFormLayout.addRow("Input Volume: ", self.inputVol)
    # input vol node connection
    self.inputVol.connect("currentNodeChanged(vtkMRMLNode*)", self.onInputVol)

    # ROI Buttons
    self.defineROIButton = qt.QPushButton("Define ROI")
    self.defineROIButton.enabled = False
    self.defineROIButton.toolTip = "Define the region/vertebrae of the interest"

    self.applyROIButton = qt.QPushButton("Crop the ROI")
    self.applyROIButton.enabled = False
    self.defineROIButton.toolTip = "Crop the region/vertebrae of the interest"
    # place them on GUI side by side
    roiFormLayout.addWidget(self.createHLayout([self.defineROIButton, self.applyROIButton]))

    self.defineROIButton.connect("clicked(bool)", self.onDefineROIButton)

    self.applyROIButton.connect("clicked(bool)", self.onApplyROIButton)


    self.thresholdGroupBox = ctk.ctkCollapsibleGroupBox()
    self.thresholdGroupBox.title = "Generate Mesh"
    self.thresholdGroupBox.collapsed = True
    roiFormLayout.addRow(self.thresholdGroupBox)
    self.thresholdGroupBox.connect('clicked(bool)' , self.onGenerateMeshGroupBox)
    
    thresholdGroupBoxLayout = qt.QFormLayout(self.thresholdGroupBox)
    # threshold value
    self.threshold = ctk.ctkRangeWidget()
    self.threshold.spinBoxAlignment = 0xff  # put enties on top
    self.threshold.singleStep = 0.1
    self.threshold.minimum = -1000
    self.threshold.maximum = 3000
    self.threshold.setToolTip(
      "Set the range of the background values that should be labeled.")
    thresholdGroupBoxLayout.addRow("Image threshold", self.threshold)
    # Generate Mesh based on the cursour movment
    
    self.generateMeshButton = qt.QPushButton("Generate Mesh")
    self.generateMeshButton.enabled = False
    self.generateMeshButton.toolTip = "Crop the region/vertebrae of the interest"
    # place them on GUI side by side
    thresholdGroupBoxLayout.addRow(self.generateMeshButton)
    
    self.generateMeshButton.connect('clicked()', self.onMeshButton)  # connection
    
    

    # Instantiate and connect widgets ...
    self.displayLayoutBox = qt.QGroupBox('Display Layout')
    self.displayLayout = qt.QGridLayout()
    self.displayLayoutBox.setLayout(self.displayLayout)
    self.layout.addWidget(self.displayLayoutBox)
        
    # button to only show preop volume 
    self.PreopOnlyButton = qt.QPushButton("Preop Only")
    self.PreopOnlyButton.name = "Preop Only"
    self.PreopOnlyButton.setCheckable(True)
    self.PreopOnlyButton.setFlat(True)
    self.displayLayout.addWidget(self.PreopOnlyButton, 0, 0)
    self.PreopOnlyButton.connect('clicked()', lambda: self.onViewMode(self.VIEW_MODE_Preop_Only))  
    
    # button to only show intraop volume 
    self.IntraopOnlyButton = qt.QPushButton("Intraop Only")
    self.IntraopOnlyButton.name = "Intraop Only"
    self.IntraopOnlyButton.setCheckable(True)
    self.IntraopOnlyButton.setFlat(True)
    self.displayLayout.addWidget(self.IntraopOnlyButton, 0, 1)
    self.IntraopOnlyButton.connect('clicked()', lambda: self.onViewMode(self.VIEW_MODE_Intraop_Only))
    
    # button to show the overalp of the intraop and preop volumes 
    self.OverlapButton = qt.QPushButton("Ax/Sa/Co")
    self.OverlapButton.name = "Ax/Sa/Co"
    self.OverlapButton.setCheckable(True)
    self.OverlapButton.setFlat(True)
    self.displayLayout.addWidget(self.OverlapButton, 0, 2)
    self.OverlapButton.connect('clicked()', lambda: self.onViewMode(self.VIEW_MODE_ThreeCompare))
    
    # button to only show Axial view of preop, intraop, and overlap  
    self.AxialButton = qt.QPushButton("Axial View")
    self.AxialButton.name = "Axial View"
    self.AxialButton.setCheckable(True)
    self.AxialButton.setFlat(True)
    self.displayLayout.addWidget(self.AxialButton, 1, 0)
    self.AxialButton.connect('clicked()', lambda: self.onViewMode(self.VIEW_MODE_Axial))
    
    # button to only show Sagittal view of preop, intraop, and overlap  
    self.SagittalButton = qt.QPushButton("Sagittal View")
    self.SagittalButton.name = "Sagittal View"
    self.SagittalButton.setCheckable(True)
    self.SagittalButton.setFlat(True)
    self.displayLayout.addWidget(self.SagittalButton, 1, 1)
    self.SagittalButton.connect('clicked()', lambda: self.onViewMode(self.VIEW_MODE_Sagittal))
    
    # button to only show Coronal view of preop, intraop, and overlap  
    self.CoronalButton = qt.QPushButton("Coronal View")
    self.CoronalButton.name = "Coronal View"
    self.CoronalButton.setCheckable(True)
    self.CoronalButton.setFlat(True)
    self.displayLayout.addWidget(self.CoronalButton, 1, 2)
    self.CoronalButton.connect('clicked()', lambda: self.onViewMode(self.VIEW_MODE_Coronal))
    
    # extra visualization    
    self.VisualizationGroupBox = ctk.ctkCollapsibleGroupBox()
    self.VisualizationGroupBox.title = "Visualization"
    self.VisualizationGroupBox.collapsed = True
    self.layout.addWidget(self.VisualizationGroupBox)
    VisualizationFormLayout = qt.QFormLayout(self.VisualizationGroupBox)
    self.visualizationWidget = RegistrationLib.VisualizationWidget(self.logic)
    b = self.visualizationWidget.widget
    allChildren = b.children()[1].children()[1].children()
    groupbox = b.children()[1].children()[1]
    groupbox.setTitle('')
    allChildren[1].hide()
    allChildren[2].hide()
    allChildren[3].hide()
    allChildren[4].hide()
    VisualizationFormLayout.addWidget(b)
    
       
   

    # Landmark Registration Area        
    fiducialregistrationwizardModuleWidget = slicer.modules.fiducialregistrationwizard.createNewWidgetRepresentation()
    fiducialregistrationwizardModuleWidgetGroupBoxes = fiducialregistrationwizardModuleWidget.findChildren("ctkCollapsibleGroupBox")
    fiducialregistrationwizardModuleWidgetQGroupBoxes = fiducialregistrationwizardModuleWidget.findChildren("QGroupBox")
    self.FidRegWizRegResultComboBox = fiducialregistrationwizardModuleWidgetQGroupBoxes[3].children()[1]
    fiducialregistrationwizardModuleWidgetGroupBoxes[2].hide() #hide the landmark from transform 
    # hide extra crap
    extra = fiducialregistrationwizardModuleWidget.children()[1].children()
    self.FiducialRegWizNode = slicer.vtkMRMLFiducialRegistrationWizardNode()
    
    slicer.mrmlScene.AddNode(self.FiducialRegWizNode)
    tag = self.FiducialRegWizNode.AddObserver(vtk.vtkCommand.ModifiedEvent, self.onFiducialRegWizNode)
    extra[1].setCurrentNode(self.FiducialRegWizNode)
    extra[1].hide()
    extra[3].hide()
    extra[4].hide()
    #registrationResult = extra[8]
    #initialregTransformBox = registrationResult.children()[1]
    #self.initialLandmarkTransform
    #initialregTransformBox.setCurrentNode(slicer.util.getNode('FromPreopToIntraopInitialTransform'))
    
    fiducialregistrationwizardModuleWidgetCollapsibleButton = fiducialregistrationwizardModuleWidget.findChildren("ctkCollapsibleButton")
    fiducialregistrationwizardModuleWidgetCollapsibleButton[0].setText('Landmark Registration')
    fiducialregistrationwizardModuleWidgetCollapsibleButton[0].collapsed = True
    #fiducialregistrationwizardModuleWidgetGroupBoxes[3].setText('')   
    self.layout.addWidget(fiducialregistrationwizardModuleWidget)
   
    
    AutoCollapsibleButton = ctk.ctkCollapsibleButton()
    AutoCollapsibleButton.text = "Auto Registrationn"
    self.layout.addWidget(AutoCollapsibleButton)
    AutoCollapsibleButton.collapsed = True
    # Layout within the dummy collapsible button
    autoFormLayout = qt.QFormLayout(AutoCollapsibleButton)
    
    self.rigidCheckmarkBox = qt.QCheckBox()
    self.rigidCheckmarkBox.checked = 1
    self.rigidCheckmarkBox.setToolTip("If checked, the rigid registration is performed (6 DOF)")
    
    self.rigidscaleCheckmarkBox = qt.QCheckBox()
    self.rigidscaleCheckmarkBox.checked = 0
    self.rigidscaleCheckmarkBox.setToolTip("If checked, the rigid and scaling is performed (7 DOF)")
   
    
    # Auto Rigid Registration Button
    self.autoRegButton = qt.QPushButton("Run Registration")
    self.autoRegButton.toolTip = "Run the automatic brains rigid registration algorithm."
    self.autoRegButton.enabled = True  
    self.autoRegButton.connect('clicked(bool)', self.onautoRegButton)  # connection
    
    # input moving mesh 
    self.inputMovingMesh = slicer.qMRMLNodeComboBox()
    self.inputMovingMesh.nodeTypes = ["vtkMRMLLabelMapVolumeNode"]
    self.inputMovingMesh.selectNodeUponCreation = True
    self.inputMovingMesh.addEnabled = False
    self.inputMovingMesh.removeEnabled = False
    self.inputMovingMesh.noneEnabled = True
    self.inputMovingMesh.showHidden = False
    self.inputMovingMesh.showChildNodeTypes = False
    self.inputMovingMesh.setMRMLScene( slicer.mrmlScene )
    self.inputMovingMesh.setToolTip( "Pick the input mesh for intraop scan" )
    
    #self.inputVol.connect("currentNodeChanged(vtkMRMLNode*)", self.onInputPreopMesh)
    
    # input fixed mesh 
    self.inputFixedMesh = slicer.qMRMLNodeComboBox()
    self.inputFixedMesh.nodeTypes = ["vtkMRMLLabelMapVolumeNode"]
    self.inputFixedMesh.selectNodeUponCreation = True
    self.inputFixedMesh.addEnabled = False
    self.inputFixedMesh.removeEnabled = False
    self.inputFixedMesh.noneEnabled = True
    self.inputFixedMesh.showHidden = False
    self.inputFixedMesh.showChildNodeTypes = False
    self.inputFixedMesh.setMRMLScene( slicer.mrmlScene )
    self.inputFixedMesh.setToolTip( "Pick the input mesh for intraop scan" )
    
   # self.inputMovingMesh.connect("currentNodeChanged(vtkMRMLNode*)", self.onInputPreopMesh)
   # self.inputFixedMesh.connect("currentNodeChanged(vtkMRMLNode*)", self.onInputIntraopMesh)
  
    autoFormLayout.addRow('Rigid (6 DOF)', self.rigidCheckmarkBox)
    autoFormLayout.addRow('Rigid+Scaling (7 DOF)', self.rigidscaleCheckmarkBox)
    
    autoFormLayout.addRow("Input Intraop Mesh: ", self.inputFixedMesh)
    autoFormLayout.addRow("Input Preop Mesh: ", self.inputMovingMesh)
    autoFormLayout.addRow(self.autoRegButton)
    # Add vertical spacer
    self.layout.addStretch(1)
Example #12
0
    def setup(self):
        # Instantiate and connect widgets ...
        ScriptedLoadableModuleWidget.setup(self)

        #self.logic = CIP_CalciumScoringLogic()

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

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

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

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

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

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

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

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

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

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

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

    ScriptedLoadableModuleWidget.setup(self)

    # Instantiate and connect widgets ...

    #
    # Parameters Area
    #
    parametersCollapsibleButton = ctk.ctkCollapsibleButton()
    parametersCollapsibleButton.text = "Liver Uptake Region Segmentation"
    self.layout.addWidget(parametersCollapsibleButton)
    parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)
    #
    # input volume selector
    #
    self.inputSelector = slicer.qMRMLNodeComboBox()
    self.inputSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
    self.inputSelector.addAttribute("vtkMRMLScalarVolumeNode", "DICOM.instanceUIDs", None)
    #self.inputSelector.addAttribute("vtkMRMLScalarVolumeNode", "DICOM.MeasurementUnitsCodeValue", "{SUVbw}g/ml") # ensures that the input is a SUV normalized PET scan
    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( "Input SUVbw normalized DICOM PET volume")
    self.inputSelector.connect("currentNodeChanged(bool)",self.refreshUIElements)
    parametersFormLayout.addRow("Input Volume", self.inputSelector)

    self.segmentationSelector = slicer.qMRMLNodeComboBox()
    self.segmentationSelector.nodeTypes = ["vtkMRMLLabelMapVolumeNode"]
    self.segmentationSelector.selectNodeUponCreation = True
    self.segmentationSelector.addEnabled = True
    self.segmentationSelector.removeEnabled = True
    self.segmentationSelector.noneEnabled = False
    self.segmentationSelector.showHidden = False
    self.segmentationSelector.showChildNodeTypes = False
    self.segmentationSelector.setMRMLScene( slicer.mrmlScene )
    self.segmentationSelector.setToolTip( "Output liver reference region volume")
    self.segmentationSelector.connect("currentNodeChanged(bool)",self.refreshUIElements)
    parametersFormLayout.addRow("Output Volume", self.segmentationSelector)

    self.regionSelector = slicer.qMRMLNodeComboBox()
    self.regionSelector.nodeTypes = ["vtkMRMLAnnotationROINode"]
    self.regionSelector.selectNodeUponCreation = True
    self.regionSelector.addEnabled = True
    self.regionSelector.removeEnabled = True
    self.regionSelector.noneEnabled = False
    self.regionSelector.showHidden = False
    self.regionSelector.showChildNodeTypes = False
    self.regionSelector.setMRMLScene( slicer.mrmlScene )
    self.regionSelector.setToolTip( "Search Region")
    self.regionSelector.connect("currentNodeChanged(bool)",self.refreshUIElements)
    parametersFormLayout.addRow("Region", self.regionSelector)

    self.thresholdRangeSlider = ctk.ctkRangeWidget()
    self.thresholdRangeSlider.minimum=0.0
    self.thresholdRangeSlider.maximum=20.0
    self.thresholdRangeSlider.singleStep = 0.1
    self.thresholdRangeSlider.minimumValue = 1.0
    self.thresholdRangeSlider.maximumValue = 10.0
    self.thresholdRangeSlider.connect("minimumValueChanged(double)",self.refreshUIElements)
    self.thresholdRangeSlider.connect("maximumValueChanged(double)",self.refreshUIElements)
    parametersFormLayout.addRow("Thresholds", self.thresholdRangeSlider)

    self.erosionSlider = ctk.ctkSliderWidget()
    self.erosionSlider.minimum=0.0
    self.erosionSlider.maximum=20.0
    self.erosionSlider.singleStep=0.1
    self.erosionSlider.value = 3.0
    self.erosionSlider.connect("valueChanged(double)",self.refreshUIElements)
    parametersFormLayout.addRow("Erosion", self.erosionSlider)

    self.segmentButton = qt.QPushButton("Segment Reference Region")
    self.segmentButton.toolTip = "Segment reference region and measure uptake"
    self.segmentButton.connect('clicked(bool)', self.onSegmentButton)
    parametersFormLayout.addRow("Segment",self.segmentButton)

    # Measurement results
    measurementsCollapsibleButton = ctk.ctkCollapsibleButton()
    measurementsCollapsibleButton.text = "Measurements"
    self.layout.addWidget(measurementsCollapsibleButton)
    parametersFormLayout = qt.QFormLayout(measurementsCollapsibleButton)

    self.meanValueLineEdit = qt.QLineEdit("-")
    self.meanValueLineEdit.setReadOnly(True)
    self.meanValueLineEdit.setToolTip( "Mean value in reference region")
    parametersFormLayout.addRow("Mean",self.meanValueLineEdit)
    self.stdValueLineEdit = qt.QLineEdit("-")
    self.stdValueLineEdit.setReadOnly(True)
    self.stdValueLineEdit.setToolTip( "Standard deviation in reference region")
    parametersFormLayout.addRow("Standard Deviation",self.stdValueLineEdit)
    self.medianValueLineEdit = qt.QLineEdit("-")
    self.medianValueLineEdit.setReadOnly(True)
    self.medianValueLineEdit.setToolTip( "Mean value in reference region")
    parametersFormLayout.addRow("Median",self.medianValueLineEdit)

    # Reporting Section
    dicomReportingCollapsibleButton = ctk.ctkCollapsibleButton()
    dicomReportingCollapsibleButton.text = "DICOM Reporting"
    self.layout.addWidget(dicomReportingCollapsibleButton)
    reportingFormLayout = qt.QFormLayout(dicomReportingCollapsibleButton)

    self.readerValueLineEdit = qt.QLineEdit(getpass.getuser())
    #self.readerValueLineEdit.setReadOnly(True)
    self.readerValueLineEdit.setToolTip( "Name of reader reporting the measurement results")
    reportingFormLayout.addRow("Reader Name",self.readerValueLineEdit)

    self.reportBoxesFrame = qt.QFrame()
    self.reportBoxesFrame.setLayout(qt.QHBoxLayout())
    self.reportBoxesFrame.layout().setSpacing(0)
    self.reportBoxesFrame.layout().setMargin(0)
    self.saveReportButton = qt.QPushButton("Save Report")
    self.saveReportButton.toolTip = "Create partially completed DICOM Structured Report which could be continued at a later time (work in progress)"
    self.saveReportButton.connect('clicked(bool)', self.onSaveReportButtonClicked)
    # note: We don't have the functionality to reload and edit a temporary report, so this option doesn't make sense for us
    #self.reportBoxesFrame.layout().addWidget(self.saveReportButton)
    self.completeReportButton = qt.QPushButton("Complete Report")
    self.completeReportButton.toolTip = "Create the completed DICOM Structured Report and save to database"
    self.completeReportButton.connect('clicked(bool)', self.onCompleteReportButtonClicked)
    self.reportBoxesFrame.layout().addWidget(self.completeReportButton)
    reportingFormLayout.addRow("Report",self.reportBoxesFrame)

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

    self.refreshUIElements()
Example #14
0
    def buildMainPanel(self, frame):

        layout = qt.QVBoxLayout(frame)

        # Point recording
        pointGroupBox = ctk.ctkCollapsibleGroupBox()
        pointGroupBox.title = "Recording"
        pointGroupBox.collapsed = False
        layout.addWidget(pointGroupBox)
        pointLayout = qt.QVBoxLayout(pointGroupBox)
        self.precording = QPointRecordingFrame(
            catheterComboBox=self.catheterComboBox)
        pointLayout.addWidget(self.precording)
        self.precording.recordPointsSelector.connect(
            "currentNodeChanged(vtkMRMLNode*)",
            self.onPointRecordingMarkupsNodeSelected)

        # Surface model
        modelGroupBox = ctk.ctkCollapsibleGroupBox()
        modelGroupBox.title = "Surface Model"
        modelGroupBox.collapsed = False
        layout.addWidget(modelGroupBox)
        #modelLayout = qt.QVBoxLayout(modelGroupBox)
        modelLayout = qt.QFormLayout(modelGroupBox)

        self.modelSelector = slicer.qMRMLNodeComboBox()
        self.modelSelector.nodeTypes = (("vtkMRMLModelNode"), "")
        self.modelSelector.selectNodeUponCreation = True
        self.modelSelector.addEnabled = True
        self.modelSelector.renameEnabled = True
        self.modelSelector.removeEnabled = True
        self.modelSelector.noneEnabled = True
        self.modelSelector.showHidden = True
        self.modelSelector.showChildNodeTypes = False
        self.modelSelector.setMRMLScene(slicer.mrmlScene)
        self.modelSelector.setToolTip("Surface model node")
        modelLayout.addRow("Model: ", self.modelSelector)

        # Point distance factor is used to generate a surface model from the point cloud
        self.pointDistanceFactorSliderWidget = ctk.ctkSliderWidget()
        self.pointDistanceFactorSliderWidget.singleStep = 0.1
        self.pointDistanceFactorSliderWidget.minimum = 0.0
        self.pointDistanceFactorSliderWidget.maximum = 20.0
        self.pointDistanceFactorSliderWidget.value = 8.0
        #self.minIntervalSliderWidget.setToolTip("")

        modelLayout.addRow("Point Disntace Factor: ",
                           self.pointDistanceFactorSliderWidget)

        self.generateSurfaceButton = qt.QPushButton()
        self.generateSurfaceButton.setCheckable(False)
        self.generateSurfaceButton.text = 'Generate Surface Map'
        self.generateSurfaceButton.setToolTip(
            "Generate a surface model from the collected points.")

        modelLayout.addRow(" ", self.generateSurfaceButton)

        # Parameter map
        mappingGroupBox = ctk.ctkCollapsibleGroupBox()
        mappingGroupBox.title = "Parameter Mapping"
        mappingGroupBox.collapsed = False
        layout.addWidget(mappingGroupBox)
        mappingLayout = qt.QFormLayout(mappingGroupBox)

        self.paramSelector = qt.QComboBox()
        self.paramSelector.addItem('None')

        mappingLayout.addRow("Egram Param:", self.paramSelector)

        self.mapModelButton = qt.QPushButton()
        self.mapModelButton.setCheckable(False)
        self.mapModelButton.text = 'Generate Color Map'
        self.mapModelButton.setToolTip(
            "Map the surface model with Egram Data.")

        # Distance threshold. We only use the points proximity to the surface model
        self.surfaceDistanceSliderWidget = ctk.ctkSliderWidget()
        self.surfaceDistanceSliderWidget.singleStep = 0.1
        self.surfaceDistanceSliderWidget.minimum = 0.0
        self.surfaceDistanceSliderWidget.maximum = 100.0
        self.surfaceDistanceSliderWidget.value = 100.0  # If 0.0, we won't pass the value to the function.
        #self.minIntervalSliderWidget.setToolTip("")
        mappingLayout.addRow("Surface Distance: ",
                             self.surfaceDistanceSliderWidget)

        # Epsilon factor for radius basis function
        # Note: The default value for scipy.interpolate.Rbf is the average distance between the points.
        #       The slider may need to be updated to what the function comes up with.
        self.epsilonSliderWidget = ctk.ctkSliderWidget()
        self.epsilonSliderWidget.singleStep = 0.1
        self.epsilonSliderWidget.minimum = 0.0
        self.epsilonSliderWidget.maximum = 100.0
        self.epsilonSliderWidget.value = 0.0  # If 0.0, we won't pass the value to the function.
        #self.minIntervalSliderWidget.setToolTip("")
        mappingLayout.addRow("Epsilon (0=Auto): ", self.epsilonSliderWidget)

        self.rbfSelector = qt.QComboBox()
        self.rbfSelector.addItem(
            'multiquadric')  # sqrt((r/self.epsilon)**2 + 1)   -- Default
        self.rbfSelector.addItem(
            'inverse')  # 1.0/sqrt((r/self.epsilon)**2 + 1)
        self.rbfSelector.addItem('gaussian')  # exp(-(r/self.epsilon)**2)
        self.rbfSelector.addItem('linear')  # r
        self.rbfSelector.addItem('cubic')  # r**3
        self.rbfSelector.addItem('quintic')  # r**5
        self.rbfSelector.addItem('thin_plate')  # r**2 * log(r)
        mappingLayout.addRow("Function:", self.rbfSelector)

        self.mapModelButton = qt.QPushButton()
        self.mapModelButton.setCheckable(False)
        self.mapModelButton.text = 'Generate Color Map'
        self.mapModelButton.setToolTip(
            "Map the surface model with Egram Data.")
        mappingLayout.addRow(" ", self.mapModelButton)

        #-- Color range
        self.colorRangeWidget = ctk.ctkRangeWidget()
        self.colorRangeWidget.setToolTip("Set color range")
        self.colorRangeWidget.setDecimals(2)
        self.colorRangeWidget.singleStep = 0.05
        self.colorRangeWidget.minimumValue = self.defaultEgramValueRange[0]
        self.colorRangeWidget.maximumValue = self.defaultEgramValueRange[1]
        self.colorRangeWidget.minimum = -50.0
        self.colorRangeWidget.maximum = 50.0
        mappingLayout.addRow("Color range: ", self.colorRangeWidget)

        #self.paramSelector.view().pressed.connect(self.onUpdateParamSelector)

        self.modelSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                   self.onModelSelected)
        self.generateSurfaceButton.connect('clicked(bool)',
                                           self.onGenerateSurface)

        self.mapModelButton.connect('clicked(bool)', self.onMapModel)
        self.colorRangeWidget.connect('valuesChanged(double, double)',
                                      self.onUpdateColorRange)
Example #15
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        # Instantiate and connect widgets ...

        #
        # File area
        #
        filesCollapsibleButton = ctk.ctkCollapsibleButton()
        filesCollapsibleButton.text = "Files"
        filesCollapsibleButton.collapsed = False
        self.layout.addWidget(filesCollapsibleButton)
        # Layout within the files collapsible button
        filesFormLayout = qt.QFormLayout(filesCollapsibleButton)

        self.fileModel = qt.QStandardItemModel()
        self.fileTable = qt.QTableView()
        self.fileTable.horizontalHeader().stretchLastSection = True
        self.fileTable.horizontalHeader().visible = False
        self.fileTable.setModel(self.fileModel)
        filesFormLayout.addRow(self.fileTable)

        buttonLayout = qt.QHBoxLayout()
        self.addByBrowsingButton = qt.QPushButton("Browse for files")
        self.clearFilesButton = qt.QPushButton("Clear files")
        buttonLayout.addWidget(self.addByBrowsingButton)
        buttonLayout.addWidget(self.clearFilesButton)
        filesFormLayout.addRow(buttonLayout)

        self.propertiesLabel = qt.QLabel()
        filesFormLayout.addRow(self.propertiesLabel)

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

        #
        # output volume selector
        #
        self.outputSelector = slicer.qMRMLNodeComboBox()

        self.outputSelector.nodeTypes = [
            "vtkMRMLScalarVolumeNode",
        ]

        self.outputSelector.showChildNodeTypes = False
        self.outputSelector.showHidden = False
        self.outputSelector.showChildNodeTypes = False
        self.outputSelector.selectNodeUponCreation = True
        self.outputSelector.noneEnabled = True
        self.outputSelector.removeEnabled = True
        self.outputSelector.renameEnabled = True
        self.outputSelector.addEnabled = True
        self.outputSelector.setMRMLScene(slicer.mrmlScene)
        self.outputSelector.setToolTip(
            "Pick the output volume to populate or None to autogenerate.")
        outputFormLayout.addRow("Output Volume: ", self.outputSelector)

        self.spacing = ctk.ctkCoordinatesWidget()
        self.spacing.decimals = 8
        self.spacing.coordinates = "1,1,1"
        self.spacing.toolTip = "Set the colunm, row, slice spacing in mm; original spacing not including downsample"
        outputFormLayout.addRow("Spacing: ", self.spacing)

        self.downsample = qt.QCheckBox()
        self.downsample.toolTip = "Reduces data size by half in each dimension by skipping every other pixel and slice (uses about 1/8 memory)"
        outputFormLayout.addRow("Downsample: ", self.downsample)

        self.reverse = qt.QCheckBox()
        self.reverse.toolTip = "Read the images in reverse order"
        outputFormLayout.addRow("Reverse: ", self.reverse)

        self.sliceSkip = ctk.ctkDoubleSpinBox()
        self.sliceSkip.decimals = 0
        self.sliceSkip.minimum = 0
        self.sliceSkip.toolTip = "Skips the selected number of slices (use, for example, on long thin samples with more slices than in-plane resolution)"
        outputFormLayout.addRow("Slice skip: ", self.sliceSkip)

        self.loadButton = qt.QPushButton("Load files")
        outputFormLayout.addRow(self.loadButton)

        #
        # Add by name area
        #
        addByNameCollapsibleButton = ctk.ctkCollapsibleButton()
        addByNameCollapsibleButton.text = "Add files by name"
        addByNameCollapsibleButton.collapsed = True
        addByNameFormLayout = qt.QFormLayout(addByNameCollapsibleButton)
        # Don't enable Add by name for now - let's see if it's actually needed
        # self.layout.addWidget(addByNameCollapsibleButton)

        forExample = """
    directoryPath = '/Volumes/SSD2T/data/SlicerMorph/Sample_for_steve/1326_Rec'
    pathFormat = '%s/1326__rec%04d.png'
    start, end =  (50, 621)
    """

        self.archetypePathEdit = ctk.ctkPathLineEdit()
        addByNameFormLayout.addRow("Archetype file", self.archetypePathEdit)

        self.archetypeFormat = qt.QLineEdit()
        addByNameFormLayout.addRow("Name format", self.archetypeFormat)

        self.indexRange = ctk.ctkRangeWidget()
        self.indexRange.decimals = 0
        self.indexRange.maximum = 0
        addByNameFormLayout.addRow("Index range", self.indexRange)

        self.generateNamesButton = qt.QPushButton("Apply")
        self.generateNamesButton.toolTip = "Run the algorithm."
        self.generateNamesButton.enabled = False
        addByNameFormLayout.addRow(self.generateNamesButton)

        # connections
        self.addByBrowsingButton.connect('clicked()', self.addByBrowsing)
        self.clearFilesButton.connect('clicked()', self.onClearFiles)
        self.archetypePathEdit.connect('currentPathChanged(QString)',
                                       self.validateInput)
        self.archetypePathEdit.connect('currentPathChanged(QString)',
                                       self.updateGUIFromArchetype)
        self.archetypeFormat.connect('textChanged(QString)',
                                     self.validateInput)
        self.generateNamesButton.connect('clicked()', self.onGenerateNames)
        # self.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.validateInput) # TODO - this is missing
        self.loadButton.connect('clicked()', self.onLoadButton)

        # refill last selection
        self.archetypePathEdit.currentPath = slicer.util.settingsValue(
            "ImageStacks/lastArchetypePath", "")

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

        # Refresh Apply button state
        self.validateInput()
Example #16
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()
Example #17
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        ###################################
        # Import node graph json file Area
        ###################################
        self.fileCollapsibleButton = ctk.ctkCollapsibleButton()
        self.fileCollapsibleButton.text = "Import Node Graph Json File"
        self.layout.addWidget(self.fileCollapsibleButton)
        self.fileImportFormLayout = qt.QFormLayout(self.fileCollapsibleButton)

        self.fileImport = ctk.ctkPathLineEdit()
        self.fileImport.filters = ctk.ctkPathLineEdit.Files
        self.fileImport.settingKey = 'JsonInputFile'
        self.fileImport.currentPath = os.path.normpath(
            os.path.join(os.path.dirname(os.path.realpath(__file__)),
                         './Resources/nodeGraph_3D.json'))
        self.fileImportFormLayout.addRow("Input Json File:", self.fileImport)

        self.fileImportButton = qt.QPushButton('Load File')
        self.fileImportFormLayout.addRow(self.fileImportButton)

        ###################################
        # Node Table Area
        ###################################
        parametersCollapsibleButton = ctk.ctkCollapsibleButton()
        parametersCollapsibleButton.text = "Node Table"
        self.layout.addWidget(parametersCollapsibleButton)
        # Layout within the collapsible button
        parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)

        #
        # Checkbox to see whether or not the input table has a header
        #
        self.headerCheckBox = qt.QCheckBox()
        self.headerCheckBox.checked = 0
        self.headerCheckBox.setToolTip(
            "If checked, it means that the input node table contains a header."
        )
        parametersFormLayout.addRow("Header in Node Table",
                                    self.headerCheckBox)

        #
        # input table selector
        #
        self.inputSelector = slicer.qMRMLNodeComboBox()
        self.inputSelector.nodeTypes = ["vtkMRMLTableNode"]
        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(
            "The input file loaded trough the import Data module should be a one line table (with or without header)."
        )
        parametersFormLayout.addRow("Input Table: ", self.inputSelector)

        #
        # Table start column spinBox
        #
        self.min_column = 1
        self.tableStartSpinBox = qt.QDoubleSpinBox()
        self.tableStartSpinBox.singleStep = 1
        self.tableStartSpinBox.setValue(self.min_column)
        self.tableStartSpinBox.setDecimals(0)
        self.tableStartSpinBox.setToolTip(
            "Set start column, if the first column contains a string of characters(ex: subject name) then this column should be skipped and the start column is thus 1. This should be an integer (int)"
        )
        parametersFormLayout.addRow("Start Column:", self.tableStartSpinBox)

        ###################################
        # Region Selector Area
        ###################################
        self.nodeselectCollapsibleButton = ctk.ctkCollapsibleButton()
        self.nodeselectCollapsibleButton.text = "Selection of Node Region"
        self.layout.addWidget(self.nodeselectCollapsibleButton)
        # Layout within the collapsible button
        self.nodeselectFormLayout = qt.QFormLayout(
            self.nodeselectCollapsibleButton)

        # Search Box to filter regions to display
        self.searchLayout = qt.QHBoxLayout()
        self.nodeselectFormLayout.addRow('Search:', self.searchLayout)
        self.regionSearchBox = ctk.ctkSearchBox()
        self.regionSearchBox.placeholderText = "search region"
        self.regionSearchBox.searchIcon
        self.searchLayout.addWidget(self.regionSearchBox)

        self.logic = visuThreeDLogic()
        self.regionsLayout = qt.QHBoxLayout()
        self.nodeselectFormLayout.addRow('Regions:', self.regionsLayout)
        self.regionButtons = ctk.ctkCheckableComboBox()
        self.regionsLayout.addWidget(self.regionButtons)

        # Add buttons to select all or no region
        self.buttonsLayout = qt.QHBoxLayout()
        self.nodeselectFormLayout.addRow('Select:', self.buttonsLayout)
        self.calculateAllregionsButton = qt.QPushButton('Select All')
        self.calculateAllregionsButton.toolTip = 'Select all regions.'
        self.calculateAllregionsButton.enabled = True
        self.buttonsLayout.addWidget(self.calculateAllregionsButton)
        self.calculateAllFilteredregionsButton = qt.QPushButton(
            'Select Filtered')
        self.calculateAllFilteredregionsButton.toolTip = 'Select all  filtered regions.'
        self.calculateAllFilteredregionsButton.enabled = True
        self.buttonsLayout.addWidget(self.calculateAllFilteredregionsButton)

        self.deselectButtonsLayout = qt.QHBoxLayout()
        self.nodeselectFormLayout.addRow('Deselect:',
                                         self.deselectButtonsLayout)
        self.calculateNoregionsButton = qt.QPushButton('Deselect All')
        self.calculateNoregionsButton.toolTip = 'Deselect all regions.'
        self.calculateNoregionsButton.enabled = True
        self.deselectButtonsLayout.addWidget(self.calculateNoregionsButton)
        self.calculateNoFilteredregionsButton = qt.QPushButton(
            'Deselect Filtered')
        self.calculateNoFilteredregionsButton.toolTip = 'Deselect all filtered regions.'
        self.calculateNoFilteredregionsButton.enabled = True
        self.deselectButtonsLayout.addWidget(
            self.calculateNoFilteredregionsButton)

        ###################################
        # Node Size and colorbar thresholding Area
        ###################################
        self.colorbarCollapsibleButton = ctk.ctkCollapsibleButton()
        self.colorbarCollapsibleButton.text = "Node Size and Color Thresholding"
        self.layout.addWidget(self.colorbarCollapsibleButton)
        # Layout within the collapsible button
        self.regioncheckFormLayout = qt.QFormLayout(
            self.colorbarCollapsibleButton)

        self.ColorTable = slicer.qMRMLColorTableComboBox()
        self.ColorTable.nodeTypes = ["vtkMRMLColorTableNode"]
        self.ColorTable.addEnabled = True
        self.ColorTable.removeEnabled = True
        self.ColorTable.noneEnabled = True
        self.ColorTable.showHidden = True
        self.ColorTable.setMRMLScene(slicer.mrmlScene)
        self.regioncheckFormLayout.addRow("Input Color Map: ", self.ColorTable)

        #
        # Threshold node value
        #
        # default values
        self.minVal = 0.0
        self.maxVal = 1.0
        self.nodeThresholdSliderWidget = ctk.ctkRangeWidget()
        self.nodeThresholdSliderWidget.singleStep = 0.01
        self.nodeThresholdSliderWidget.setValues(self.minVal, self.maxVal)
        self.nodeThresholdSliderWidget.setMaximumValue(self.maxVal)
        self.nodeThresholdSliderWidget.setMinimumValue(self.minVal)
        self.nodeThresholdSliderWidget.setRange(self.minVal, self.maxVal)
        self.nodeThresholdSliderWidget.setMouseTracking(True)
        self.nodeThresholdSliderWidget.setEnabled(True)
        self.nodeThresholdSliderWidget.setToolTip(
            "Set threshold node value for computing the node value.")
        self.regioncheckFormLayout.addRow("Plot Property Range:",
                                          self.nodeThresholdSliderWidget)

        #
        # Node size min spinBox
        #
        # default value for min size (l: lowest , h: highest)
        self.minSize_l = 0.0
        self.minSize_h = 100.0
        self.nodeMinSizeSpinBox = qt.QDoubleSpinBox()
        self.nodeMinSizeSpinBox.singleStep = 0.01
        self.nodeMinSizeSpinBox.setRange(self.minSize_l, self.minSize_h)
        self.nodeMinSizeSpinBox.setToolTip("Set minimum node size.")
        self.regioncheckFormLayout.addRow("Min Size:", self.nodeMinSizeSpinBox)

        #
        # Node size max spinBox
        #
        # default value for max size (l: lowest , h: highest)
        self.maxSize_l = 0.0
        self.maxSize_h = 100.0
        self.nodeMaxSizeSpinBox = qt.QDoubleSpinBox()
        self.nodeMaxSizeSpinBox.singleStep = 0.01
        self.nodeMaxSizeSpinBox.setRange(self.maxSize_l, self.maxSize_h)
        self.nodeMaxSizeSpinBox.setToolTip("Set maximum node size.")
        self.regioncheckFormLayout.addRow("Max Size:", self.nodeMaxSizeSpinBox)

        ###################################
        # Connections line/tube Area
        ###################################
        self.lineCollapsibleButton = ctk.ctkCollapsibleButton()
        self.lineCollapsibleButton.text = "Connection Size and Color Thresholding"
        self.layout.addWidget(self.lineCollapsibleButton)
        # Layout within the collapsible button
        self.lineconnectFormLayout = qt.QFormLayout(self.lineCollapsibleButton)

        #
        # input connection matrix selector
        #
        self.matrixConnectSelector = slicer.qMRMLNodeComboBox()
        self.matrixConnectSelector.nodeTypes = ["vtkMRMLTableNode"]
        self.matrixConnectSelector.selectNodeUponCreation = True
        self.matrixConnectSelector.addEnabled = False
        self.matrixConnectSelector.removeEnabled = False
        self.matrixConnectSelector.noneEnabled = False
        self.matrixConnectSelector.showHidden = False
        self.matrixConnectSelector.showChildNodeTypes = False
        self.matrixConnectSelector.setMRMLScene(slicer.mrmlScene)
        self.matrixConnectSelector.setToolTip(
            "Pick the connection matrix input to the algorithm.")
        self.lineconnectFormLayout.addRow("Input Connection Table: ",
                                          self.matrixConnectSelector)

        #
        # Checkbox to choose whether or not the connection distribution follows a log scale or else a linear distribution
        #
        self.connectionDistCheckBox = qt.QCheckBox()
        self.connectionDistCheckBox.checked = 0
        self.connectionDistCheckBox.setToolTip(
            "If checked, it means that the connection distribution follows a log scale."
        )
        self.lineconnectFormLayout.addRow("Log Distribution",
                                          self.connectionDistCheckBox)

        self.connectionColorTable = slicer.qMRMLColorTableComboBox()
        self.connectionColorTable.nodeTypes = ["vtkMRMLColorTableNode"]
        self.connectionColorTable.addEnabled = True
        self.connectionColorTable.removeEnabled = True
        self.connectionColorTable.noneEnabled = True
        self.connectionColorTable.showHidden = True
        self.connectionColorTable.setMRMLScene(slicer.mrmlScene)
        self.lineconnectFormLayout.addRow("Input Color Map: ",
                                          self.connectionColorTable)

        #
        # Threshold node connection strength
        #
        # default values
        self.logic = visuThreeDLogic()
        self.min_strength = 0.0
        self.max_strength = 1.0
        self.connectionThresholdSliderWidget = ctk.ctkRangeWidget()
        self.connectionThresholdSliderWidget.singleStep = 0.01
        self.connectionThresholdSliderWidget.setValues(self.min_strength,
                                                       self.max_strength)
        self.connectionThresholdSliderWidget.setMaximumValue(self.max_strength)
        self.connectionThresholdSliderWidget.setMinimumValue(self.min_strength)
        self.connectionThresholdSliderWidget.setRange(self.minVal,
                                                      self.max_strength)
        self.connectionThresholdSliderWidget.setMouseTracking(True)
        self.connectionThresholdSliderWidget.setEnabled(True)
        self.connectionThresholdSliderWidget.setToolTip(
            "Set threshold node value for computing the node value.")
        self.lineconnectFormLayout.addRow("Plot Strength Range:",
                                          self.connectionThresholdSliderWidget)

        #
        # Connection min strength spinBox
        #
        # default value for min strength (l: lowest , h: highest)
        self.minStrength_l = 0.0
        self.minStrength_h = 50.0
        self.minConnectionSpinBox = qt.QDoubleSpinBox()
        self.minConnectionSpinBox.singleStep = 0.01
        self.minConnectionSpinBox.setRange(self.minStrength_l,
                                           self.minStrength_h)
        self.minConnectionSpinBox.setToolTip(
            "Set minimum connection strength.")
        self.lineconnectFormLayout.addRow("Min Strength:",
                                          self.minConnectionSpinBox)

        #
        # Node size max spinBox
        #
        # default value for max size (l: lowest , h: highest)
        self.maxStrength_l = 0.0
        self.maxStrength_h = 100.0
        self.maxConnectionSpinBox = qt.QDoubleSpinBox()
        self.maxConnectionSpinBox.singleStep = 0.01
        self.maxConnectionSpinBox.setRange(self.maxStrength_l,
                                           self.maxStrength_h)
        self.maxConnectionSpinBox.setToolTip(
            "Set maximum connection strength.")
        self.lineconnectFormLayout.addRow("Max Strenght:",
                                          self.maxConnectionSpinBox)

        ###################################
        # Advanced Connections scale factors Area
        ###################################
        self.scaleCollapsibleButton = ctk.ctkCollapsibleButton()
        self.scaleCollapsibleButton.text = "Advanced Connection Scale Factors"
        self.layout.addWidget(self.scaleCollapsibleButton)
        # Layout within the collapsible button
        self.scaleconnectFormLayout = qt.QFormLayout(
            self.scaleCollapsibleButton)

        #Double SpinBox for default scale factor "f" :
        #computation of value in matrix by the number of connexions * f factor
        self.fscaleDoubleSpinBox = ctk.ctkDoubleSpinBox()
        self.fscaleDoubleSpinBox.setValue(0.000033)
        self.fscaleDoubleSpinBox.setDecimals(6)
        self.fscaleDoubleSpinBox.enabled = True
        self.scaleconnectFormLayout.addWidget(self.fscaleDoubleSpinBox)
        self.scaleconnectFormLayout.addRow("f Scale:",
                                           self.fscaleDoubleSpinBox)

        #Double SpinBox for log scale factor "C" :
        self.logScaleDoubleSpinBox = ctk.ctkDoubleSpinBox()
        self.logScaleDoubleSpinBox.setValue(10)
        self.logScaleDoubleSpinBox.setDecimals(0.)
        self.logScaleDoubleSpinBox.enabled = False
        self.scaleconnectFormLayout.addWidget(self.logScaleDoubleSpinBox)
        self.scaleconnectFormLayout.addRow("C Log Scale:",
                                           self.logScaleDoubleSpinBox)

        ###################################
        # Connections
        ###################################
        self.coord = []
        self.index = []
        self.position = []
        self.visu = []
        self.fileImportButton.connect('clicked(bool)',
                                      self.on_node_graph_json_load)
        self.inputSelector.connect("nodeActivated(vtkMRMLNode*)",
                                   self.on_select)
        self.regionButtons.connect('checkedIndexesChanged()',
                                   self.on_regions_checked)
        self.calculateAllFilteredregionsButton.connect(
            'clicked(bool)', self.on_select_all_filtered_regionButtons)
        self.calculateAllregionsButton.connect(
            'clicked(bool)', self.on_select_all_regionButtons)
        self.calculateNoregionsButton.connect(
            'clicked(bool)', self.on_deselect_all_regionButtons)
        self.calculateNoFilteredregionsButton.connect(
            'clicked(bool)', self.on_deselect_all_filtered_regionButtons)
        self.regionSearchBox.connect("textChanged(QString)", self.on_search)
        self.ColorTable.connect("currentNodeChanged(vtkMRMLNode*)",
                                self.on_node_color_clicked)
        self.nodeThresholdSliderWidget.connect("valuesChanged(double, double)",
                                               self.sliderbar_changed)
        self.nodeMinSizeSpinBox.connect("valueChanged(double)",
                                        self.min_nodesize_changed)
        self.nodeMaxSizeSpinBox.connect("valueChanged(double)",
                                        self.max_nodesize_changed)
        self.tableStartSpinBox.connect("valueChanged(double)",
                                       self.table_start_changed)
        self.matrixConnectSelector.connect("nodeActivated(vtkMRMLNode*)",
                                           self.on_select_matrix)
        self.connectionThresholdSliderWidget.connect(
            "valuesChanged(double, double)", self.sliderbar2_changed)
        self.maxConnectionSpinBox.connect("valueChanged(double)",
                                          self.max_connection_changed)
        self.connectionColorTable.connect("currentNodeChanged(vtkMRMLNode*)",
                                          self.on_connect_color_clicked)
        self.fscaleDoubleSpinBox.connect("valueChanged(double)",
                                         self.on_fscale_changed)
        self.logScaleDoubleSpinBox.connect("valueChanged(double)",
                                           self.on_logscale_changed)

        # Add vertical spacer
        self.layout.addStretch(1)
        self.header = None
        self.connection_d = None
        self.value = 'None'
        self.on_node_graph_json_load()
    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)

        #
        # threshold value
        #

        self.thresholdSlider = ctk.ctkRangeWidget()
        self.thresholdSlider.spinBoxAlignment = qt.Qt.AlignTop
        self.thresholdSlider.singleStep = 0.01
        self.thresholdSlider.minimum = 0
        self.thresholdSlider.maximum = 1
        self.thresholdSlider.minimumValue = 0
        self.thresholdSlider.maximumValue = 1
        self.thresholdSlider.enabled = False
        parametersFormLayout.addRow("Image threshold : min - max",
                                    self.thresholdSlider)

        #

        self.TLS_per_min_2=\
        {"TFL": {"272": {"COM": {"0.15": {"vpp": 0.007655, "f": [50, 100, 150, 200]},
                                 "0.5": {"vpp": 0.050916667,"f":[15, 30, 45, 60]},
                                 "1.": {"vpp": 0.0744, "f": [7.5, 10, 15, 20, 22.5, 30]},
                                 },
                         "UA": {"0.15": {"vpp": 0.00748, "f": [50, 100, 150, 200]},
                                "0.5": {"vpp": 0.0524, "f": [15, 30, 45, 60]},
                                "1.": {"vpp": 0.073966667, "f": [7.5, 10, 15, 20, 22.5, 30]},
                                },
                         },
                 "150": {"COM": {"0.15": {"vpp": 0.0059466667, "f": [50, 100, 150, 200]},
                                 "0.5": {"vpp": 0.031983333, "f": [15, 30, 45, 60]},
                                 "1.": {"vpp": 0.045788889, "f": [7.5, 10, 15, 20, 22.5, 30]},
                                 },
                         "UA": {"0.15": {"vpp": 0.006295, "f": [50, 100, 150, 200]},
                                "0.5": {"vpp": 0.034266667, "f": [15, 30, 45, 60]},
                                "1.": {"vpp": 0.055733333, "f": [7.5, 10, 15, 20, 22.5, 30]},
                                },
                         },
                 },
        "HO:YAG": {"272": {"COM": {"0.5": {"vpp": 0.01355, "f": [15, 30, 45, 60]},
                                   "1.": {"vpp": 0.035266667, "f": [7.5, 10, 15, 20, 22.5, 30]}
                                   },
                           "UA": {"0.5": {"vpp": 0.019158333, "f": [15, 30, 45, 60]},
                                  "1.": {"vpp": 0.042888889, "f": [7.5, 10, 15, 20, 22.5, 30]},
                                  },
                           },
                   }
        }

        self.lpreset=\
        [{"type": "TFL", "name": "Fine Dusting", "e": "0.15", "f": 100},
         {"type": "TFL", "name": "Dusting", "e": "0.5", "f": 30},
         {"type": "TFL", "name": "Fragmentation", "e": "1.", "f": 15},
         {"type": "HO:YAG", "name": "Dusting", "e": "0.5", "f": 30},
         {"type": "HO:YAG", "name": "Fragmentation", "e": "1.", "f": 15},
        ]

        self.laser_combobox = ctk.ctkComboBox()
        for i in self.TLS_per_min_2.keys():
            self.laser_combobox.addItem(i)
        self.laser_combobox.enabled = True
        parametersFormLayout.addRow("Laser source", self.laser_combobox)

        self.d_fiber_combobox = ctk.ctkComboBox()
        self.d_fiber_combobox.enabled = True
        parametersFormLayout.addRow(u"laser fiber diameter (\u03BCm)",
                                    self.d_fiber_combobox)

        self.TypeOfStone_combobox = ctk.ctkComboBox()
        self.TypeOfStone_combobox.enabled = True
        parametersFormLayout.addRow("Type of Stone", self.TypeOfStone_combobox)

        self.ManualPreset_combobox = ctk.ctkComboBox()
        self.ManualPreset_combobox.enabled = True
        parametersFormLayout.addRow(self.ManualPreset_combobox)

        self.EnergyJ_combobox = ctk.ctkComboBox()
        self.EnergyJ_combobox.enabled = True
        parametersFormLayout.addRow("Energy (J)", self.EnergyJ_combobox)

        self.Frequence_combobox = ctk.ctkComboBox()
        self.Frequence_combobox.enabled = True
        parametersFormLayout.addRow("Pulse Rate(Hz)", self.Frequence_combobox)

        #
        # voxels split
        #

        self.splitVoxelsCheckBox = ctk.ctkCheckBox()
        self.splitVoxelsCheckBox.checked = False
        parametersFormLayout.addRow("split islands to segments",
                                    self.splitVoxelsCheckBox)

        #

        self.minimumSizeSpinBox = qt.QSpinBox()
        self.minimumSizeSpinBox.setToolTip(
            "Islands consisting of less voxels than this minimum size, will be deleted."
        )
        self.minimumSizeSpinBox.setMinimum(0)
        self.minimumSizeSpinBox.setMaximum(vtk.VTK_INT_MAX)
        self.minimumSizeSpinBox.setValue(1000)
        self.minimumSizeSpinBox.suffix = " voxels"
        parametersFormLayout.addRow("Minimum size:", self.minimumSizeSpinBox)
        self.minimumSizeSpinBox.enabled = False
        #
        # Preview results in 3D
        #

        self.previewShow3DCheckBox = qt.QCheckBox()
        self.previewShow3DCheckBox.setToolTip("Preview results in 3D.")
        self.previewShow3DCheckBox.enabled = True
        self.previewShow3DCheckBox.checked = False
        parametersFormLayout.addRow("Show in 3D", self.previewShow3DCheckBox)

        #
        # check box to trigger taking screen shots for later use in tutorials
        #
        self.enableScreenshotsFlagCheckBox = qt.QCheckBox()
        self.enableScreenshotsFlagCheckBox.checked = 0
        self.enableScreenshotsFlagCheckBox.setToolTip(
            "If checked, take screen shots for tutorials. Use Save Data to write them to disk."
        )
        parametersFormLayout.addRow("Enable Screenshots",
                                    self.enableScreenshotsFlagCheckBox)

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

        #

        self.applyButton.connect('clicked(bool)', self.onApplyButton)
        self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                   self.onSelect)
        self.splitVoxelsCheckBox.connect('clicked(bool)', self.onCheckSplit)
        self.previewShow3DCheckBox.connect('clicked(bool)',
                                           self.onCheckpreviewShow3D)

        self.laser_combobox.connect("activated(int)", self.onLaserSelect)
        self.d_fiber_combobox.connect("activated(int)", self.ondfiberSelect)
        self.TypeOfStone_combobox.connect("activated(int)",
                                          self.onTypeOfStoneSelect)
        self.ManualPreset_combobox.connect("activated(int)",
                                           self.onManualPresetSelect)
        self.EnergyJ_combobox.connect("activated(int)", self.onEnergyJSelect)

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

        # Refresh Apply button state
        self.onSelect()

        self.onLaserSelect()
  def setupOptionsFrame(self):
    self.thresholdSliderLabel = qt.QLabel("Threshold Range:")
    self.thresholdSliderLabel.setToolTip("Set the range of the background values that should be labeled.")
    self.scriptedEffect.addOptionsWidget(self.thresholdSliderLabel)

    self.thresholdSlider = ctk.ctkRangeWidget()
    self.thresholdSlider.spinBoxAlignment = qt.Qt.AlignTop
    self.thresholdSlider.singleStep = 0.01
    self.scriptedEffect.addOptionsWidget(self.thresholdSlider)

    self.autoThresholdModeSelectorComboBox = qt.QComboBox()
    self.autoThresholdModeSelectorComboBox.addItem("auto->maximum", MODE_SET_LOWER_MAX)
    self.autoThresholdModeSelectorComboBox.addItem("minimum->auto", MODE_SET_MIN_UPPER)
    self.autoThresholdModeSelectorComboBox.addItem("as lower", MODE_SET_LOWER)
    self.autoThresholdModeSelectorComboBox.addItem("as upper", MODE_SET_UPPER)
    self.autoThresholdModeSelectorComboBox.setToolTip("How to set lower and upper threshold values. Current refers to keeping the current value.")

    self.autoThresholdMethodSelectorComboBox = qt.QComboBox()
    self.autoThresholdMethodSelectorComboBox.addItem("Otsu", METHOD_OTSU)
    self.autoThresholdMethodSelectorComboBox.addItem("Huang", METHOD_HUANG)
    self.autoThresholdMethodSelectorComboBox.addItem("IsoData", METHOD_ISO_DATA)
    # Kittler-Illingworth sometimes fails with an exception, but it does not cause any major issue,
    # it just logs an error message and does not compute a new threshold value
    self.autoThresholdMethodSelectorComboBox.addItem("Kittler-Illingworth", METHOD_KITTLER_ILLINGWORTH)
    # Li sometimes crashes (index out of range error in
    # ITK/Modules/Filtering/Thresholding/include/itkLiThresholdCalculator.hxx#L94)
    # We can add this method back when issue is fixed in ITK.
    #self.autoThresholdMethodSelectorComboBox.addItem("Li", METHOD_LI)
    self.autoThresholdMethodSelectorComboBox.addItem("Maximum entropy", METHOD_MAXIMUM_ENTROPY)
    self.autoThresholdMethodSelectorComboBox.addItem("Moments", METHOD_MOMENTS)
    self.autoThresholdMethodSelectorComboBox.addItem("Renyi entropy", METHOD_RENYI_ENTROPY)
    self.autoThresholdMethodSelectorComboBox.addItem("Shanbhag", METHOD_SHANBHAG)
    self.autoThresholdMethodSelectorComboBox.addItem("Triangle", METHOD_TRIANGLE)
    self.autoThresholdMethodSelectorComboBox.addItem("Yen", METHOD_YEN)
    self.autoThresholdMethodSelectorComboBox.setToolTip("Select method to compute threshold value automatically.")

    self.selectPreviousAutoThresholdButton = qt.QToolButton()
    self.selectPreviousAutoThresholdButton.text = "<"
    self.selectPreviousAutoThresholdButton.setToolTip("Select previous thresholding method and set thresholds."
      +" Useful for iterating through all available methods.")

    self.selectNextAutoThresholdButton = qt.QToolButton()
    self.selectNextAutoThresholdButton.text = ">"
    self.selectNextAutoThresholdButton.setToolTip("Select next thresholding method and set thresholds."
      +" Useful for iterating through all available methods.")

    self.setAutoThresholdButton = qt.QPushButton("Set")
    self.setAutoThresholdButton.setToolTip("Set threshold using selected method.")

    # qt.QSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    # fails on some systems, therefore set the policies using separate method calls
    qSize = qt.QSizePolicy()
    qSize.setHorizontalPolicy(qt.QSizePolicy.Expanding)
    self.setAutoThresholdButton.setSizePolicy(qSize)

    autoThresholdFrame = qt.QHBoxLayout()
    autoThresholdFrame.addWidget(self.autoThresholdModeSelectorComboBox)
    autoThresholdFrame.addWidget(self.autoThresholdMethodSelectorComboBox)
    autoThresholdFrame.addWidget(self.selectPreviousAutoThresholdButton)
    autoThresholdFrame.addWidget(self.selectNextAutoThresholdButton)
    autoThresholdFrame.addWidget(self.setAutoThresholdButton)
    self.scriptedEffect.addLabeledOptionsWidget("Automatic threshold:", autoThresholdFrame)

    self.useForPaintButton = qt.QPushButton("Use for masking")
    self.useForPaintButton.setToolTip("Use specified intensity range for masking and switch to Paint effect.")
    self.scriptedEffect.addOptionsWidget(self.useForPaintButton)

    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.objectName = self.__class__.__name__ + 'Apply'
    self.applyButton.setToolTip("Fill selected segment in regions that are in the specified intensity range.")
    self.scriptedEffect.addOptionsWidget(self.applyButton)

    self.useForPaintButton.connect('clicked()', self.onUseForPaint)
    self.thresholdSlider.connect('valuesChanged(double,double)', self.onThresholdValuesChanged)
    self.autoThresholdMethodSelectorComboBox.connect("activated(int)", self.onSelectedAutoThresholdMethod)
    self.autoThresholdModeSelectorComboBox.connect("activated(int)", self.onSelectedAutoThresholdMethod)
    self.selectPreviousAutoThresholdButton.connect('clicked()', self.onSelectPreviousAutoThresholdMethod)
    self.selectNextAutoThresholdButton.connect('clicked()', self.onSelectNextAutoThresholdMethod)
    self.setAutoThresholdButton.connect('clicked()', self.onAutoThreshold)
    self.applyButton.connect('clicked()', self.onApply)
Example #20
0
    def create(self):
        super(TraceAndSelectOptions, self).create()

        ## Custom threshold box
        # Note: This is needed because other tools can disable, hide, or manipulate the default threshold box
        # We need one unique to our tool
        self.threshLabel = qt.QLabel("Threshold", self.frame)
        self.threshLabel.setToolTip(
            "In threshold mode, the label will only be set if the background value is within this range."
        )
        self.frame.layout().addWidget(self.threshLabel)
        self.widgets.append(self.threshLabel)
        self.thresh = ctk.ctkRangeWidget(self.frame)
        self.thresh.spinBoxAlignment = 0xff  # put enties on top
        self.thresh.singleStep = 0.01
        self.setRangeWidgetToBackgroundRange(self.thresh)
        self.frame.layout().addWidget(self.thresh)
        self.widgets.append(self.thresh)
        ## End custom threshold box

        ## Preview checkbox
        self.preview = qt.QCheckBox("Preview outlines", self.frame)
        self.preview.setToolTip(
            "Preview the outline of a selection with right-click.")
        self.frame.layout().addWidget(self.preview)
        ## End preview checkbox

        self.modeButtons = qt.QButtonGroup(self.frame)
        self.tissueRadioButton = qt.QRadioButton("Tissue Mode", self.frame)
        self.boneRadioButton = qt.QRadioButton("Bone/Nerve Mode", self.frame)
        self.hbox = qt.QHBoxLayout()
        self.hbox.addWidget(self.boneRadioButton)
        self.hbox.addWidget(self.tissueRadioButton)
        self.frame.layout().addLayout(self.hbox)
        self.modeButtons.addButton(self.boneRadioButton)
        self.modeButtons.addButton(self.tissueRadioButton)

        self.widgets.append(self.tissueRadioButton)
        self.widgets.append(self.boneRadioButton)

        ## ERROR MESSAGE FRAME
        self.errorMessageFrame = qt.QTextEdit(self.frame)
        self.frame.layout().addWidget(self.errorMessageFrame)
        #self.errorMessageFrame.setLayout(qt.QHBoxLayout)
        self.errorMessageFrame.setFixedWidth(280)
        self.errorMessageFrame.setReadOnly(True)
        self.errorMessageFrame.setText('No Error Detected')
        self.errorMessageFrame.setStyleSheet("QTextEdit {color:green}")
        self.widgets.append(self.errorMessageFrame)
        ## END ERROR MESSAGE FRAME

        ## For the offset value selection process
        self.offsetvalueFrame = qt.QFrame(self.frame)
        self.offsetvalueFrame.setLayout(qt.QHBoxLayout())
        self.frame.layout().addWidget(self.offsetvalueFrame)
        self.widgets.append(self.offsetvalueFrame)
        self.offsetvalueLabel = qt.QLabel("Offset Value:",
                                          self.offsetvalueFrame)
        self.offsetvalueLabel.setToolTip(
            "Set the offset value shift upon an action")
        self.offsetvalueFrame.layout().addWidget(self.offsetvalueLabel)
        self.widgets.append(self.offsetvalueLabel)
        self.offsetvalueSpinBox = qt.QDoubleSpinBox(self.offsetvalueFrame)
        self.offsetvalueSpinBox.setToolTip(
            "Set the offset value shift upon an action")
        self.offsetvalueSpinBox.minimum = -1000
        self.offsetvalueSpinBox.maximum = 1000
        self.offsetvalueSpinBox.suffix = ""
        self.offsetvalueFrame.layout().addWidget(self.offsetvalueSpinBox)
        self.widgets.append(self.offsetvalueSpinBox)
        ## End offset value selection

        self.maxPixelsFrame = qt.QFrame(self.frame)
        self.maxPixelsFrame.setLayout(qt.QHBoxLayout())
        self.frame.layout().addWidget(self.maxPixelsFrame)
        self.widgets.append(self.maxPixelsFrame)
        self.maxPixelsLabel = qt.QLabel("Max Pixels per click:",
                                        self.maxPixelsFrame)
        self.maxPixelsLabel.setToolTip("Set the maxPixels for each click")
        self.maxPixelsFrame.layout().addWidget(self.maxPixelsLabel)
        self.widgets.append(self.maxPixelsLabel)
        self.maxPixelsSpinBox = qt.QDoubleSpinBox(self.maxPixelsFrame)
        self.maxPixelsSpinBox.setToolTip("Set the maxPixels for each click")
        self.maxPixelsSpinBox.minimum = 1
        self.maxPixelsSpinBox.maximum = 100000
        self.maxPixelsSpinBox.suffix = ""
        self.maxPixelsFrame.layout().addWidget(self.maxPixelsSpinBox)
        self.widgets.append(self.maxPixelsSpinBox)

        # Help Browser
        self.helpBrowser = qt.QPushButton("Visit the Webpage")

        # End Help Browser
        self.frame.layout().addWidget(self.helpBrowser)

        HelpButton(
            self.frame,
            "Use this tool to help you label all voxels enclosed in an area bounded by the the largest path of pixels within the specified threshold."
        )

        # don't connect the signals and slots directly - instead, add these
        # to the list of connections so that gui callbacks can be cleanly
        # disabled while the gui is being updated.  This allows several gui
        # elements to be interlinked with signal/slots but still get updated
        # as a unit to the new value of the mrml node.
        # self.thresholdPaint.hide()
        self.connections.append((self.maxPixelsSpinBox, 'valueChanged(double)',
                                 self.onMaxPixelsSpinBoxChanged))
        self.connections.append(
            (self.preview, "clicked()", self.onPreviewChanged))

        self.connections.append(
            (self.tissueRadioButton, "clicked()", self.onTissueButtonChanged))
        self.connections.append(
            (self.boneRadioButton, "clicked()", self.onBoneButtonChanged))

        self.connections.append(
            (self.offsetvalueSpinBox, 'valueChanged(double)',
             self.onOffsetValueSpinBoxChanged))
        self.connections.append((self.thresh, "valuesChanged(double,double)",
                                 self.onThreshValuesChange))

        self.connections.append(
            (self.helpBrowser, "clicked()", self.onHelpBrowserPressed))

        # Add vertical spacer
        self.frame.layout().addStretch(1)
Example #21
0
  def setup(self):
    ScriptedLoadableModuleWidget.setup(self)

    # Instantiate and connect widgets ...


    #
    # File area
    #
    filesCollapsibleButton = ctk.ctkCollapsibleButton()
    filesCollapsibleButton.text = "Files"
    filesCollapsibleButton.collapsed = False
    self.layout.addWidget(filesCollapsibleButton)
    # Layout within the files collapsible button
    filesFormLayout = qt.QFormLayout(filesCollapsibleButton)

    self.fileModel = qt.QStandardItemModel()
    self.fileTable = qt.QTableView()
    self.fileTable.horizontalHeader().stretchLastSection = True
    self.fileTable.horizontalHeader().visible = False
    self.fileTable.setModel(self.fileModel)
    filesFormLayout.addRow(self.fileTable)

    buttonLayout = qt.QHBoxLayout()
    self.addByBrowsingButton = qt.QPushButton("Browse for files")
    self.clearFilesButton = qt.QPushButton("Clear files")
    buttonLayout.addWidget(self.addByBrowsingButton)
    buttonLayout.addWidget(self.clearFilesButton)
    filesFormLayout.addRow(buttonLayout)

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

    #
    # output volume selector
    #
    #self.outputSelector = slicer.qMRMLSubjectHierarchyComboBox()
    self.outputSelector = slicer.qMRMLNodeComboBox()

    self.outputSelector.nodeTypes = ["vtkMRMLScalarVolumeNode",]
    #self.outputSelector.setNodeTypes(["vtkMRMLScalarVolumeNode",]) ; TODO: make nodeTypes property for SH box


    """
    TODO: which are supported and needed for SubjectHierarchy combo box.
    TODO: can we delete/rename/create as with SH
    self.outputSelector.defaultText = "Create new volume." ; # TODO any way to reset value?
    """
    self.outputSelector.showChildNodeTypes = False
    self.outputSelector.showHidden = False
    self.outputSelector.showChildNodeTypes = False
    self.outputSelector.selectNodeUponCreation = False
    self.outputSelector.noneEnabled = True
    self.outputSelector.removeEnabled = True
    self.outputSelector.renameEnabled = True
    self.outputSelector.addEnabled = True
    self.outputSelector.setMRMLScene( slicer.mrmlScene )
    self.outputSelector.setToolTip( "Pick the output volume to populate or None to autogenerate." )
    outputFormLayout.addRow("Output Volume: ", self.outputSelector)

    self.spacing = ctk.ctkCoordinatesWidget()
    self.spacing.coordinates = "1,1,1"
    self.spacing.toolTip = "Set the colunm, row, slice spacing in mm"
    outputFormLayout.addRow("Spacing: ", self.spacing)


    self.loadButton = qt.QPushButton("Load files")
    outputFormLayout.addRow(self.loadButton)

    #
    # Add by name area
    #
    addByNameCollapsibleButton = ctk.ctkCollapsibleButton()
    addByNameCollapsibleButton.text = "Add files by name"
    addByNameCollapsibleButton.collapsed = True
    addByNameFormLayout = qt.QFormLayout(addByNameCollapsibleButton)
    # Don't enable Add by name for now - let's see if it's actually needed
    # self.layout.addWidget(addByNameCollapsibleButton)

    forExample = """
    directoryPath = '/Volumes/SSD2T/data/SlicerMorph/Sample_for_steve/1326_Rec'
    pathFormat = '%s/1326__rec%04d.png'
    start, end =  (50, 621)
    """

    self.archetypePathEdit = ctk.ctkPathLineEdit()
    addByNameFormLayout.addRow("Archetype file", self.archetypePathEdit)

    self.archetypeFormat = qt.QLineEdit()
    addByNameFormLayout.addRow("Name format", self.archetypeFormat)

    self.indexRange = ctk.ctkRangeWidget()
    self.indexRange.decimals = 0
    self.indexRange.maximum = 0
    addByNameFormLayout.addRow("Index range", self.indexRange)

    self.generateNamesButton = qt.QPushButton("Apply")
    self.generateNamesButton.toolTip = "Run the algorithm."
    self.generateNamesButton.enabled = False
    addByNameFormLayout.addRow(self.generateNamesButton)

    # connections
    self.addByBrowsingButton.connect('clicked()', self.addByBrowsing)
    self.clearFilesButton.connect('clicked()', self.fileTable.model().clear)
    self.archetypePathEdit.connect('currentPathChanged(QString)', self.validateInput)
    self.archetypePathEdit.connect('currentPathChanged(QString)', self.updateGUIFromArchetype)
    self.archetypeFormat.connect('textChanged(QString)', self.validateInput)
    self.generateNamesButton.connect('clicked()', self.onGenerateNames)
    # self.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.validateInput) # TODO - this is missing
    self.loadButton.connect('clicked()', self.onLoadButton)

    # refill last selection
    self.archetypePathEdit.currentPath = slicer.util.settingsValue("ImageStacks/lastArchetypePath", "")


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

    # Refresh Apply button state
    self.validateInput()
  def setupOptionsFrame(self):
    self.thresholdSliderLabel = qt.QLabel("Threshold Range:")
    self.thresholdSliderLabel.setToolTip("Set the range of the background values that should be labeled.")
    self.scriptedEffect.addOptionsWidget(self.thresholdSliderLabel)

    self.thresholdSlider = ctk.ctkRangeWidget()
    self.thresholdSlider.spinBoxAlignment = qt.Qt.AlignTop
    self.thresholdSlider.singleStep = 0.01
    self.scriptedEffect.addOptionsWidget(self.thresholdSlider)

    self.autoThresholdModeSelectorComboBox = qt.QComboBox()
    self.autoThresholdModeSelectorComboBox.addItem("auto->maximum", MODE_SET_LOWER_MAX)
    self.autoThresholdModeSelectorComboBox.addItem("minimum->auto", MODE_SET_MIN_UPPER)
    self.autoThresholdModeSelectorComboBox.addItem("as lower", MODE_SET_LOWER)
    self.autoThresholdModeSelectorComboBox.addItem("as upper", MODE_SET_UPPER)
    self.autoThresholdModeSelectorComboBox.setToolTip("How to set lower and upper threshold values. Current refers to keeping the current value.")

    self.autoThresholdMethodSelectorComboBox = qt.QComboBox()
    self.autoThresholdMethodSelectorComboBox.addItem("Otsu", METHOD_OTSU)
    self.autoThresholdMethodSelectorComboBox.addItem("Huang", METHOD_HUANG)
    self.autoThresholdMethodSelectorComboBox.addItem("IsoData", METHOD_ISO_DATA)
    self.autoThresholdMethodSelectorComboBox.addItem("Kittler-Illingworth", METHOD_KITTLER_ILLINGWORTH)
    self.autoThresholdMethodSelectorComboBox.addItem("Li", METHOD_LI)
    self.autoThresholdMethodSelectorComboBox.addItem("Maximum entropy", METHOD_MAXIMUM_ENTROPY)
    self.autoThresholdMethodSelectorComboBox.addItem("Moments", METHOD_MOMENTS)
    self.autoThresholdMethodSelectorComboBox.addItem("Renyi entropy", METHOD_RENYI_ENTROPY)
    self.autoThresholdMethodSelectorComboBox.addItem("Shanbhag", METHOD_SHANBHAG)
    self.autoThresholdMethodSelectorComboBox.addItem("Triangle", METHOD_TRIANGLE)
    self.autoThresholdMethodSelectorComboBox.addItem("Yen", METHOD_YEN)
    self.autoThresholdMethodSelectorComboBox.setToolTip("Select method to compute threshold value automatically.")

    self.selectPreviousAutoThresholdButton = qt.QPushButton("<")
    self.selectPreviousAutoThresholdButton.setToolTip("Select previous thresholding method and set thresholds using that."
      +" Useful for iterating through all available methods.")

    self.setAutoThresholdButton = qt.QPushButton("Reset")
    self.setAutoThresholdButton.setToolTip("Set threshold using selected method.")

    self.selectNextAutoThresholdButton = qt.QPushButton(">")
    self.selectNextAutoThresholdButton.setToolTip("Select next thresholding method and set thresholds using that."
      +" Useful for iterating through all available methods.")

    # qt.QSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
    # fails on some systems, therefore set the policies using separate method calls
    qSize = qt.QSizePolicy()
    qSize.setHorizontalPolicy(qt.QSizePolicy.Expanding)
    self.setAutoThresholdButton.setSizePolicy(qSize)

    autoThresholdFrame = qt.QHBoxLayout()
    autoThresholdFrame.addWidget(self.autoThresholdModeSelectorComboBox)
    autoThresholdFrame.addWidget(self.autoThresholdMethodSelectorComboBox)
    autoThresholdFrame.addWidget(self.selectPreviousAutoThresholdButton)
    autoThresholdFrame.addWidget(self.setAutoThresholdButton)
    autoThresholdFrame.addWidget(self.selectNextAutoThresholdButton)
    self.scriptedEffect.addLabeledOptionsWidget("Automatic threshold:", autoThresholdFrame)

    self.useForPaintButton = qt.QPushButton("Use for masking")
    self.useForPaintButton.setToolTip("Use specified intensity range for masking and switch to Paint effect.")
    self.scriptedEffect.addOptionsWidget(self.useForPaintButton)

    self.applyButton = qt.QPushButton("Apply")
    self.applyButton.objectName = self.__class__.__name__ + 'Apply'
    self.applyButton.setToolTip("Fill selected segment in regions that are in the specified intensity range.")
    self.scriptedEffect.addOptionsWidget(self.applyButton)

    self.useForPaintButton.connect('clicked()', self.onUseForPaint)
    self.thresholdSlider.connect('valuesChanged(double,double)', self.onThresholdValuesChanged)
    self.autoThresholdMethodSelectorComboBox.connect("activated(int)", self.onSelectedAutoThresholdMethod)
    self.autoThresholdModeSelectorComboBox.connect("activated(int)", self.onSelectedAutoThresholdMethod)
    self.selectPreviousAutoThresholdButton.connect('clicked()', self.onSelectPreviousAutoThresholdMethod)
    self.selectNextAutoThresholdButton.connect('clicked()', self.onSelectNextAutoThresholdMethod)
    self.setAutoThresholdButton.connect('clicked()', self.onAutoThreshold)
    self.applyButton.connect('clicked()', self.onApply)
Example #23
0
    def setup(self):
        ScriptedLoadableModuleWidget.setup(self)

        self.logic = PFileParserLogic()

        # 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)

        # %%%%%%%%%%%%%%%  Read PFile button section %%%%%%%%%%%%%%

        # Collapsible bar
        pCollapsibleBar = ctk.ctkCollapsibleButton()
        pCollapsibleBar.text = "fMRSI data"
        self.layout.addWidget(pCollapsibleBar)

        # Layout within the sample collapsible button
        formLayout = qt.QFormLayout(pCollapsibleBar)

        # Frame input edit sub-layout
        frameLayout = qt.QHBoxLayout(pCollapsibleBar)

        pStartAtFrameText = self.createFrameText(
            frameLayout, "From frame: ", 100,
            "First frame to be read from fMRSI file (1 = first).")

        # Add spacer
        frameLayout.addStretch(1)

        # Text input frame end
        pStopAtFrameText = self.createFrameText(
            frameLayout, "To frame: ", 100,
            "Last frame to be read from fMRSI file.")

        # Add horizontal frame to form layout
        formLayout.addRow(frameLayout)

        # ============== Buttons ==============
        # Button widget code
        pFileButton = qt.QPushButton("Read PFile...")
        pFileButton.toolTip = "Load raw PFile (.7) data"
        pFileButton.enabled = False
        formLayout.addRow(pFileButton)

        # =============== Radio Buttons ========
        self.units = ("ppm", "hz", "points")

        pUnitsBox = qt.QGroupBox("Units")
        pUnitsBox.enabled = False
        pUnitsBox.setLayout(qt.QFormLayout())
        pUnitsButtons = {}
        for units in self.units:
            pUnitsButtons[units] = qt.QRadioButton()
            pUnitsButtons[units].text = units
            pUnitsBox.layout().addRow(pUnitsButtons[units])

        self.selectedUnits = self.units[0]
        pUnitsButtons[self.selectedUnits].checked = True
        formLayout.addRow(pUnitsBox)

        # =============== Sliders ==============

        # Frame slider
        pFrameSlider = ctk.ctkSliderWidget()
        pFrameSlider.decimals = 0
        pFrameSlider.minimum = 1
        pFrameSlider.maximum = 1
        pFrameSlider.enabled = False
        formLayout.addRow("Frame:", pFrameSlider)

        # X axis Slider
        pXAxisRange = ctk.ctkRangeWidget()
        pXAxisRange.enabled = False
        pXAxisRange.minimum = 0.0
        pXAxisRange.maximum = 0.0

        formLayout.addRow("X axis range:", pXAxisRange)

        # Button widget code
        pPlotSpectrumButton = qt.QPushButton("Plot Spectrum...")
        pPlotSpectrumButton.toolTip = "Plot mean single voxel spectrum from PFile (.7) data"
        pPlotSpectrumButton.enabled = False
        formLayout.addRow(pPlotSpectrumButton)

        # ============== Info Text ==============
        # Text Info
        pInfoText = qt.QTextEdit()
        pInfoText.setReadOnly(True)
        pInfoText.setToolTip("Data read from fMRSI file.")
        formLayout.addRow(pInfoText)

        # connections
        pFileButton.connect('clicked(bool)', self.onPFileButtonClicked)
        pPlotSpectrumButton.connect('clicked(bool)',
                                    self.onPlotSpectrumButtonClicked)
        self.inputSelector.connect('currentNodeChanged(vtkMRMLNode*)',
                                   self.onSelect)

        for units in self.units:
            pUnitsButtons[units].connect(
                'clicked()', lambda u=units: self.onPUnitsButtonsClicked(u))

        # Set local var as instance attribute
        self.pFileButton = pFileButton
        self.pPlotSpectrumButton = pPlotSpectrumButton
        self.pInfoText = pInfoText
        self.pStartAtFrameText = pStartAtFrameText
        self.pStopAtFrameText = pStopAtFrameText
        self.pFrameSlider = pFrameSlider
        self.pXAxisRange = pXAxisRange
        self.pUnitsBox = pUnitsBox
        self.pUnitsButtons = pUnitsButtons

        # Add spacer
        self.layout.addStretch(1)

        # Refresh button status
        self.onSelect()
Example #24
0
    def setup(self):
        # Instantiate and connect widgets ...
        ScriptedLoadableModuleWidget.setup(self)

        #self.logic = CIP_CalciumScoringLogic()

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

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

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

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

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

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


        #
        # Save Widget Area
        #

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

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

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

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

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

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

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

        #Create the 'Input/Output' drop down in the module
        IOCollapsibleButton = ctk.ctkCollapsibleButton()
        IOCollapsibleButton.text = "Input/Output"
        self.layout.addWidget(IOCollapsibleButton)
        IOFormLayout = qt.QFormLayout(IOCollapsibleButton)

        #Create the 'parameters' drop down in the module
        parametersCollapsibleButton = ctk.ctkCollapsibleButton()
        parametersCollapsibleButton.text = "Parameters"
        self.layout.addWidget(parametersCollapsibleButton)
        parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)

        #Create the input selector for input volume
        self.inputSelector = slicer.qMRMLNodeComboBox()
        self.inputSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
        self.inputSelector.selectNodeUponCreation = False
        self.inputSelector.addEnabled = False
        self.inputSelector.removeEnabled = False
        self.inputSelector.noneEnabled = True
        self.inputSelector.showHidden = False
        self.inputSelector.showChildNodeTypes = False
        self.inputSelector.setMRMLScene(slicer.mrmlScene)
        self.inputSelector.setToolTip("Select the input.")
        IOFormLayout.addRow("Input Image Volume: ", self.inputSelector)

        #Create the output selector for output volume
        self.outputSelector = slicer.qMRMLNodeComboBox()
        self.outputSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"]
        self.outputSelector.selectNodeUponCreation = True
        self.outputSelector.addEnabled = True
        self.outputSelector.removeEnabled = True
        self.outputSelector.noneEnabled = True
        self.outputSelector.showHidden = False
        self.outputSelector.showChildNodeTypes = False
        self.outputSelector.setMRMLScene(slicer.mrmlScene)
        self.outputSelector.setToolTip("Select the output.")
        IOFormLayout.addRow("Output Image Volume: ", self.outputSelector)

        #Create a slider that allows user to set threshold
        self.ThresholdSlider = ctk.ctkRangeWidget()
        self.ThresholdSlider.singleStep = 1
        self.ThresholdSlider.minimum = -500
        self.ThresholdSlider.maximum = 1000
        self.ThresholdSlider.setValues(150, 1000)
        self.ThresholdSlider.setToolTip(
            "Set the minimum and maximum threshold for use with BinaryThreshold"
        )
        parametersFormLayout.addRow("Threshold:", self.ThresholdSlider)
        """
    self.fiducialSelector = slicer.qMRMLNodeComboBox()
    self.fiducialSelector.nodeTypes = ["vtkMRMLFiducialListNode"]
    self.fiducialSelector.selectNodeUponCreation = True
    self.fiducialSelector.addEnabled = True
    self.fiducialSelector.removeEnabled = True
    self.fiducialSelector.noneEnabled = True
    self.fiducialSelector.showHidden = False
    self.fiducialSelector.showChildNodeTypes = False
    self.fiducialSelector.setMRMLScene(slicer.mrmlScene)
    self.fiducialSelector.setToolTip("Pick fiducial points for seeds of thresholding")
    parametersFormLayout.addRow("Fiducial: ", self.fiducialSelector)
    """

        #Create a combo box to let the user select the image filter
        self.filterSelector = qt.QComboBox()
        parametersFormLayout.addRow("Filter:", self.filterSelector)
        self.filterSelector.addItem('Curvature Flow')
        self.filterSelector.addItem('Smoothing Recursive Gaussian')
        self.filterSelector.addItem('Discrete Gaussian')
        self.filterSelector.addItem('Shot Noise')

        #Create the 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.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                   self.onSelect)
        self.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                    self.onSelect)
        self.filterSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                    self.onSelect)

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

        # Refresh Apply button state
        self.onSelect()
Example #26
0
    def buildMainPanel(self, frame):

        layout = qt.QVBoxLayout(frame)
        selectorLayout = qt.QFormLayout()
        layout.addLayout(selectorLayout)

        self.activeTrackingCheckBox = qt.QCheckBox()
        self.activeTrackingCheckBox.checked = 0
        self.activeTrackingCheckBox.enabled = 1
        self.activeTrackingCheckBox.setToolTip("Activate Tracking")
        selectorLayout.addRow("Active: ", self.activeTrackingCheckBox)

        #--------------------------------------------------
        # Coil Selection
        #
        coilGroupBox = ctk.ctkCollapsibleGroupBox()
        coilGroupBox.title = "Source / Coil Selection"
        coilGroupBox.collapsed = False

        layout.addWidget(coilGroupBox)
        coilSelectionLayout = qt.QFormLayout(coilGroupBox)

        self.trackingDataSelector = slicer.qMRMLNodeComboBox()
        self.trackingDataSelector.nodeTypes = ((
            "vtkMRMLIGTLTrackingDataBundleNode"), "")
        self.trackingDataSelector.selectNodeUponCreation = True
        self.trackingDataSelector.addEnabled = True
        self.trackingDataSelector.removeEnabled = False
        self.trackingDataSelector.noneEnabled = False
        self.trackingDataSelector.showHidden = True
        self.trackingDataSelector.showChildNodeTypes = False
        self.trackingDataSelector.setMRMLScene(slicer.mrmlScene)
        self.trackingDataSelector.setToolTip("Incoming tracking data")
        coilSelectionLayout.addRow("Source: ", self.trackingDataSelector)

        #
        # Coil seleciton check boxes
        #
        self.nChannel = 8
        self.coilCheckBox = [None for i in range(self.nChannel)]

        for ch in range(self.nChannel):
            self.coilCheckBox[ch] = qt.QCheckBox()
            self.coilCheckBox[ch].checked = 0
            self.coilCheckBox[ch].text = "CH %d" % (ch + 1)

        nChannelHalf = int(self.nChannel / 2)

        coilGroup1Layout = qt.QHBoxLayout()
        for ch in range(nChannelHalf):
            coilGroup1Layout.addWidget(self.coilCheckBox[ch])
        coilSelectionLayout.addRow("Active Coils:", coilGroup1Layout)

        coilGroup2Layout = qt.QHBoxLayout()
        for ch in range(nChannelHalf):
            coilGroup2Layout.addWidget(self.coilCheckBox[ch + nChannelHalf])
        coilSelectionLayout.addRow("", coilGroup2Layout)

        self.coilOrderDistalRadioButton = qt.QRadioButton("Distal First")
        self.coilOrderDistalRadioButton.checked = 1
        self.coilOrderProximalRadioButton = qt.QRadioButton("Proximal First")
        self.coilOrderProximalRadioButton.checked = 0
        self.coilOrderButtonGroup = qt.QButtonGroup()
        self.coilOrderButtonGroup.addButton(self.coilOrderDistalRadioButton)
        self.coilOrderButtonGroup.addButton(self.coilOrderProximalRadioButton)

        coilOrderGroupLayout = qt.QHBoxLayout()
        coilOrderGroupLayout.addWidget(self.coilOrderDistalRadioButton)
        coilOrderGroupLayout.addWidget(self.coilOrderProximalRadioButton)
        coilSelectionLayout.addRow("Coil Order:", coilOrderGroupLayout)

        #--------------------------------------------------
        # Catheter Configuration

        configGroupBox = ctk.ctkCollapsibleGroupBox()
        configGroupBox.title = "Catheter Configuration"
        configGroupBox.collapsed = False

        layout.addWidget(configGroupBox)
        configFormLayout = qt.QFormLayout(configGroupBox)

        #
        # Catheter #cath Catheter diameter
        #
        self.catheterDiameterSliderWidget = ctk.ctkSliderWidget()
        self.catheterDiameterSliderWidget.singleStep = 0.1
        self.catheterDiameterSliderWidget.minimum = 0.1
        self.catheterDiameterSliderWidget.maximum = 10.0
        self.catheterDiameterSliderWidget.value = 1.0
        self.catheterDiameterSliderWidget.setToolTip(
            "Set the diameter of the catheter")
        configFormLayout.addRow("Diameter (mm): ",
                                self.catheterDiameterSliderWidget)

        #
        # Catheter #cath Catheter opacity
        #
        self.catheterOpacitySliderWidget = ctk.ctkSliderWidget()
        self.catheterOpacitySliderWidget.singleStep = 0.1
        self.catheterOpacitySliderWidget.minimum = 0.0
        self.catheterOpacitySliderWidget.maximum = 1.0
        self.catheterOpacitySliderWidget.value = 1.0
        self.catheterOpacitySliderWidget.setToolTip(
            "Set the opacity of the catheter")
        configFormLayout.addRow("Opacity: ", self.catheterOpacitySliderWidget)

        #
        # Catheter color
        #
        colorLayout = qt.QHBoxLayout()
        self.colorButton = qt.QPushButton()
        self.colorButton.setCheckable(False)
        self.colorButton.text = '  '
        self.colorButton.setToolTip("Change the color of the catheter.")
        colorLayout.addWidget(self.colorButton)
        colorLayout.addStretch(2)
        #configFormLayout.addRow("Color: ", self.colorButton)
        configFormLayout.addRow("Color: ", colorLayout)

        #
        # Catheter #cath "Use coil positions for registration" check box
        #
        self.catheterRegUseCoilCheckBox = qt.QCheckBox()
        self.catheterRegUseCoilCheckBox.checked = 1
        self.catheterRegUseCoilCheckBox.enabled = 1
        self.catheterRegUseCoilCheckBox.setToolTip("Activate Tracking")
        configFormLayout.addRow("Cath Use Coil Pos: ",
                                self.catheterRegUseCoilCheckBox)

        #
        # Catheter #cath registration points
        #
        #  Format: (<coil index>,<offset>),(<coil index>,<offset>),...
        #
        self.catheterRegPointsLineEdit = qt.QLineEdit()
        self.catheterRegPointsLineEdit.text = '5.0,10.0,15.0,20.0'
        self.catheterRegPointsLineEdit.readOnly = False
        self.catheterRegPointsLineEdit.frame = True
        #self.catheterRegPointsLineEdit.styleSheet = "QLineEdit { background:transparent; }"
        configFormLayout.addRow("Coil positions: ",
                                self.catheterRegPointsLineEdit)

        #
        # Check box to show/hide coil labels
        #
        self.showCoilLabelCheckBox = qt.QCheckBox()
        self.showCoilLabelCheckBox.checked = 0
        self.showCoilLabelCheckBox.setToolTip("Show/hide coil labels")
        configFormLayout.addRow("Show Coil Labels: ",
                                self.showCoilLabelCheckBox)

        #
        # Sheath
        #
        self.sheathRangeLineEdit = qt.QLineEdit()
        self.sheathRangeLineEdit.text = '0-3'
        self.sheathRangeLineEdit.readOnly = False
        self.sheathRangeLineEdit.frame = True
        configFormLayout.addRow('Sheath Coils (e.g., "0-3"): ',
                                self.sheathRangeLineEdit)

        #--------------------------------------------------
        # Coordinate System
        #
        coordinateGroupBox = ctk.ctkCollapsibleGroupBox()
        coordinateGroupBox.title = "Coordinate System"
        coordinateGroupBox.collapsed = False

        layout.addWidget(coordinateGroupBox)
        coordinateLayout = qt.QFormLayout(coordinateGroupBox)

        self.coordinateRPlusRadioButton = qt.QRadioButton("+X")
        self.coordinateRMinusRadioButton = qt.QRadioButton("-X")
        self.coordinateRPlusRadioButton.checked = 1
        self.coordinateRBoxLayout = qt.QHBoxLayout()
        self.coordinateRBoxLayout.addWidget(self.coordinateRPlusRadioButton)
        self.coordinateRBoxLayout.addWidget(self.coordinateRMinusRadioButton)
        self.coordinateRGroup = qt.QButtonGroup()
        self.coordinateRGroup.addButton(self.coordinateRPlusRadioButton)
        self.coordinateRGroup.addButton(self.coordinateRMinusRadioButton)
        coordinateLayout.addRow("Right:", self.coordinateRBoxLayout)

        self.coordinateAPlusRadioButton = qt.QRadioButton("+Y")
        self.coordinateAMinusRadioButton = qt.QRadioButton("-Y")
        self.coordinateAPlusRadioButton.checked = 1
        self.coordinateABoxLayout = qt.QHBoxLayout()
        self.coordinateABoxLayout.addWidget(self.coordinateAPlusRadioButton)
        self.coordinateABoxLayout.addWidget(self.coordinateAMinusRadioButton)
        self.coordinateAGroup = qt.QButtonGroup()
        self.coordinateAGroup.addButton(self.coordinateAPlusRadioButton)
        self.coordinateAGroup.addButton(self.coordinateAMinusRadioButton)
        coordinateLayout.addRow("Anterior:", self.coordinateABoxLayout)

        self.coordinateSPlusRadioButton = qt.QRadioButton("+Z")
        self.coordinateSMinusRadioButton = qt.QRadioButton("-Z")
        self.coordinateSPlusRadioButton.checked = 1
        self.coordinateSBoxLayout = qt.QHBoxLayout()
        self.coordinateSBoxLayout.addWidget(self.coordinateSPlusRadioButton)
        self.coordinateSBoxLayout.addWidget(self.coordinateSMinusRadioButton)
        self.coordinateSGroup = qt.QButtonGroup()
        self.coordinateSGroup.addButton(self.coordinateSPlusRadioButton)
        self.coordinateSGroup.addButton(self.coordinateSMinusRadioButton)
        coordinateLayout.addRow("Superior:", self.coordinateSBoxLayout)

        #--------------------------------------------------
        # Stabilizer
        #
        stabilizerGroupBox = ctk.ctkCollapsibleGroupBox()
        stabilizerGroupBox.title = "Stabilizer"
        stabilizerGroupBox.collapsed = False

        layout.addWidget(stabilizerGroupBox)
        stabilizerLayout = qt.QFormLayout(stabilizerGroupBox)

        self.cutoffFrequencySliderWidget = ctk.ctkSliderWidget()
        self.cutoffFrequencySliderWidget.singleStep = 0.1
        self.cutoffFrequencySliderWidget.minimum = 0.10
        self.cutoffFrequencySliderWidget.maximum = 50.0
        self.cutoffFrequencySliderWidget.value = 7.5
        #self.cutoffFrequencySliderWidget.setToolTip("")
        stabilizerLayout.addRow("Cut-off frequency: ",
                                self.cutoffFrequencySliderWidget)

        self.triggerComboBox = QComboBoxCatheter()
        self.triggerComboBox.setCatheterCollection(self.catheters)
        self.triggerComboBox.setCurrentCatheterNone()
        stabilizerLayout.addRow("Acq. Trigger:", self.triggerComboBox)

        #-- Tracking data acquisition window.
        self.windowRangeWidget = ctk.ctkRangeWidget()
        self.windowRangeWidget.setToolTip("Set acquisition window (ms)")
        self.windowRangeWidget.setDecimals(3)
        self.windowRangeWidget.singleStep = 1
        self.windowRangeWidget.minimumValue = 0.0
        self.windowRangeWidget.maximumValue = 1000.0
        self.windowRangeWidget.minimum = 0.0
        self.windowRangeWidget.maximum = 1000.0
        stabilizerLayout.addRow("Acq. Window:", self.windowRangeWidget)

        #--------------------------------------------------
        # Egram
        #
        egramGroupBox = ctk.ctkCollapsibleGroupBox()
        egramGroupBox.title = "Egram Data"
        egramGroupBox.collapsed = False

        layout.addWidget(egramGroupBox)
        egramLayout = qt.QFormLayout(egramGroupBox)

        self.egramDataSelector = slicer.qMRMLNodeComboBox()
        self.egramDataSelector.nodeTypes = (("vtkMRMLTextNode"), "")
        self.egramDataSelector.selectNodeUponCreation = True
        self.egramDataSelector.addEnabled = True
        self.egramDataSelector.removeEnabled = False
        self.egramDataSelector.noneEnabled = False
        self.egramDataSelector.showHidden = True
        self.egramDataSelector.showChildNodeTypes = False
        self.egramDataSelector.setMRMLScene(slicer.mrmlScene)
        self.egramDataSelector.setToolTip("Incoming Egram data")

        egramLayout.addRow("Egram Cath: ", self.egramDataSelector)

        #--------------------------------------------------
        # Save Configuration
        #

        trackingDataSaveFrame = qt.QFrame()
        trackingDataSaveLayout = qt.QHBoxLayout(trackingDataSaveFrame)

        trackingDataSaveLayout.addStretch(1)

        self.saveConfigButton = qt.QPushButton()
        self.saveConfigButton.setCheckable(False)
        self.saveConfigButton.text = 'Save'
        self.saveConfigButton.setToolTip("Save/add current configurations.")

        self.removeConfigButton = qt.QPushButton()
        self.removeConfigButton.setCheckable(False)
        self.removeConfigButton.text = 'Remove'
        self.removeConfigButton.setToolTip("Remove current configurations.")

        self.saveDefaultConfigButton = qt.QPushButton()
        self.saveDefaultConfigButton.setCheckable(False)
        self.saveDefaultConfigButton.text = 'Save as Default'
        self.saveDefaultConfigButton.setToolTip(
            "Save above configurations as default.")

        trackingDataSaveLayout.addWidget(self.saveConfigButton)
        trackingDataSaveLayout.addWidget(self.removeConfigButton)
        trackingDataSaveLayout.addWidget(self.saveDefaultConfigButton)

        layout.addWidget(trackingDataSaveFrame)

        #--------------------------------------------------
        # Connections
        #
        self.activeTrackingCheckBox.connect('clicked(bool)',
                                            self.onActiveTracking)
        self.trackingDataSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                          self.onTrackingDataSelected)
        self.egramDataSelector.connect("currentNodeChanged(vtkMRMLNode*)",
                                       self.onEgramDataSelected)
        self.catheterRegPointsLineEdit.editingFinished.connect(
            self.onCatheterRegPointsChanged)
        self.sheathRangeLineEdit.editingFinished.connect(
            self.onCatheterSheathRangeChanged)
        self.catheterDiameterSliderWidget.connect(
            "valueChanged(double)", self.onCatheterDiameterChanged)
        self.catheterOpacitySliderWidget.connect("valueChanged(double)",
                                                 self.onCatheterOpacityChanged)
        self.colorButton.connect('clicked(bool)', self.onColorButtonClicked)
        self.showCoilLabelCheckBox.connect('clicked(bool)',
                                           self.onCoilLabelChecked)

        for ch in range(self.nChannel):
            self.coilCheckBox[ch].connect('clicked(bool)', self.onCoilChecked)

        self.coilOrderDistalRadioButton.connect('clicked(bool)',
                                                self.onCoilChecked)
        self.coilOrderProximalRadioButton.connect('clicked(bool)',
                                                  self.onCoilChecked)
        self.coordinateRPlusRadioButton.connect('clicked(bool)',
                                                self.onSelectCoordinate)
        self.coordinateRMinusRadioButton.connect('clicked(bool)',
                                                 self.onSelectCoordinate)
        self.coordinateAPlusRadioButton.connect('clicked(bool)',
                                                self.onSelectCoordinate)
        self.coordinateAMinusRadioButton.connect('clicked(bool)',
                                                 self.onSelectCoordinate)
        self.coordinateSPlusRadioButton.connect('clicked(bool)',
                                                self.onSelectCoordinate)
        self.coordinateSMinusRadioButton.connect('clicked(bool)',
                                                 self.onSelectCoordinate)
        self.cutoffFrequencySliderWidget.connect(
            "valueChanged(double)", self.onStabilizerCutoffChanged)
        self.windowRangeWidget.connect('valuesChanged(double, double)',
                                       self.onUpdateWindow)

        self.saveConfigButton.connect('clicked(bool)', self.onSaveConfig)
        self.removeConfigButton.connect('clicked(bool)', self.onRemoveConfig)
        self.saveDefaultConfigButton.connect('clicked(bool)',
                                             self.onSaveDefaultConfig)

        self.triggerComboBox.currentIndexChanged.connect(
            self.onTriggerSelected)

        #--------------------------------------------------
        # Load catheter configurations
        #

        # TODO: Should it be done in MRTrackingLogic or CatheterCollection?

        self.loadSavedConfig()