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