def __init__(self, parent): self.vLayout = qt.QVBoxLayout(parent) self.formLayout = qt.QFormLayout() self.componentName = qt.QLineEdit() self.formLayout.addRow("Name:", self.componentName) self.componentNameValidator = qt.QRegExpValidator( qt.QRegExp(r"^[a-zA-Z_][a-zA-Z0-9_]*$")) self.componentName.setValidator(self.componentNameValidator) self.componentType = qt.QComboBox() self.formLayout.addRow("Type:", self.componentType) self.destination = ctk.ctkPathLineEdit() self.destination.filters = ctk.ctkPathLineEdit.Dirs self.formLayout.addRow("Destination:", self.destination) self.vLayout.addLayout(self.formLayout) self.vLayout.addStretch(1) self.buttonBox = qt.QDialogButtonBox() self.buttonBox.setStandardButtons(qt.QDialogButtonBox.Ok | qt.QDialogButtonBox.Cancel) self.vLayout.addWidget(self.buttonBox)
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 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) # # Select landmark file to import # self.inputFileSelector = ctk.ctkPathLineEdit() self.inputFileSelector.filters = ctk.ctkPathLineEdit().Files self.inputFileSelector.setToolTip( "Select surface image that will be imported as a segment for editing" ) parametersFormLayout.addRow("Select surface file to edit:", self.inputFileSelector) # # 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 conversion." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.inputFileSelector.connect('validInputChanged(bool)', self.onSelectInput) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelectInput()
def createUserInterface(self): layout = qt.QFormLayout(self) layout.setVerticalSpacing(5) loadCaseGroupBox = qt.QGroupBox() loadCaseGroupBox.title = "Load Volume" loadCaseGroupBox.setToolTip("Select the volume to load.") loadCaseFormLayout = qt.QFormLayout(loadCaseGroupBox) loadCaseFormLayout.setContentsMargins(10, 10, 10, 10) self.loadCaseSelector = ctk.ctkPathLineEdit() self.loadCaseSelector.filters = ctk.ctkPathLineEdit.Files loadCaseFormLayout.addRow("NRRD Volume:", self.loadCaseSelector) self.loadCaseSelector.connect('currentPathChanged(const QString)', self.loadSavedCase) layout.addWidget(loadCaseGroupBox) activeVolumeGroupBox = qt.QGroupBox() activeVolumeGroupBox.title = "Active Volume Data" layout.addWidget(activeVolumeGroupBox) activeVolumeFormLayout = qt.QFormLayout(activeVolumeGroupBox) activeVolumeFormLayout.setContentsMargins(10, 10, 10, 10) self.__inputSelector = slicer.qMRMLNodeComboBox() self.__inputSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.__inputSelector.addEnabled = False self.__inputSelector.removeEnabled = False self.__inputSelector.setMRMLScene(slicer.mrmlScene) activeVolumeFormLayout.addRow(self.__inputSelector) qt.QTimer.singleShot(0, self.killButton)
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) # # Select landmark file to import # self.inputFileSelector = ctk.ctkPathLineEdit() self.inputFileSelector.setToolTip( "Select landmark file for import" ) parametersFormLayout.addRow("Select file containing landmark names and coordinates to load:", self.inputFileSelector) # # Get header length # self.headerLengthWidget = ctk.ctkDoubleSpinBox() self.headerLengthWidget.value = 2 self.headerLengthWidget.minimum = 0 self.headerLengthWidget.singleStep = 1 self.headerLengthWidget.setToolTip("Input the number of lines in header") parametersFormLayout.addRow("Header length:", self.headerLengthWidget) # # 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) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.inputFileSelector.connect('validInputChanged(bool)', self.onSelect) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelect()
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) self.inputDirectory=ctk.ctkPathLineEdit() self.inputDirectory.filters=ctk.ctkPathLineEdit.Dirs self.inputDirectory.setToolTip( "Select input directory" ) parametersFormLayout.addRow("Input folder:", self.inputDirectory) self.outputDirectory=ctk.ctkPathLineEdit() self.outputDirectory.filters=ctk.ctkPathLineEdit.Dirs self.outputDirectory.setToolTip( "Select output directory") parametersFormLayout.addRow("Output folder: ", self.outputDirectory) # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Convert." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # connections self.inputDirectory.connect('validInputChanged(bool)', self.onSelect) self.outputDirectory.connect('validInputChanged(bool)', self.onSelect) self.applyButton.connect('clicked(bool)', self.onApplyButton) # Add vertical spacer self.layout.addStretch(1)
def setup(self): # Collapsible button ioCollapsible = ctk.ctkCollapsibleButton() ioCollapsible.text = "Input and Output Selection" self.layout.addWidget(ioCollapsible) # Layout within the sample collapsible button ioFormLayout = qt.QFormLayout(ioCollapsible) # input directory selection self.inputDirSelector = ctk.ctkPathLineEdit() self.inputDirSelector.filters = ctk.ctkPathLineEdit.Dirs self.inputDirSelector.options = ctk.ctkPathLineEdit.ShowDirsOnly self.inputDirSelector.settingKey = 'inputDir' ioFormLayout.addRow("Input Directory:", self.inputDirSelector) # output directory selection self.outputDirSelector = ctk.ctkPathLineEdit() self.outputDirSelector.filters = ctk.ctkPathLineEdit.Dirs self.outputDirSelector.options = ctk.ctkPathLineEdit.ShowDirsOnly self.outputDirSelector.settingKey = 'outputDir' ioFormLayout.addRow("Empty Output Directory:", self.outputDirSelector) # transform file selection self.transformationSelector = ctk.ctkPathLineEdit() self.transformationSelector.filters = ctk.ctkPathLineEdit.Files self.transformationSelector.settingKey = 'transformationFile' ioFormLayout.addRow("Transform file:", self.transformationSelector) # button to run runTransformButton = qt.QPushButton("Harden Transform") runTransformButton.toolTip = "Harden models in selected directory and save to output directory." ioFormLayout.addWidget(runTransformButton) runTransformButton.connect('clicked(bool)', self.onrunTransformButtonClicked) # Set local var as instance attribute self.runTransformButton = runTransformButton
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 directory selector # with It(ctk.ctkPathLineEdit()) as w: self.inputDirectorySelector = w # make a directory-only, save dialog w.filters = ctk.ctkPathLineEdit.Dirs | ctk.ctkPathLineEdit.Writable parametersFormLayout.addRow("Input Directory: ", w) # # Apply Button # with It(qt.QPushButton("Apply")) as w: self.applyButton = w w.toolTip = "Run the algorithm." w.enabled = False parametersFormLayout.addRow(w) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.inputDirectorySelector.connect( 'currentPathChanged(const QString&)', self.reset) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelect()
def makeGUI(self): self.setDirButton = ctk.ctkCollapsibleButton() self.setDirButton.text = 'Select dataset directory' setDirLayout = qt.QFormLayout(self.setDirButton) self.layout.addWidget(self.setDirButton) self.datasetDirEdit = ctk.ctkPathLineEdit() self.datasetDirEdit.filters = ctk.ctkPathLineEdit.Dirs setDirLayout.addRow('EPISURG directory: ', self.datasetDirEdit) self.datasetDirButton = qt.QPushButton('Load subjects') self.datasetDirButton.clicked.connect(self.onLoadSubjectsButton) setDirLayout.addWidget(self.datasetDirButton) self.downloadDatasetButton = qt.QPushButton('Download dataset') self.downloadDatasetButton.clicked.connect( self.onDownloadDatasetButton) setDirLayout.addWidget(self.downloadDatasetButton) self.subjectsButton = ctk.ctkCollapsibleButton() self.subjectsButton.text = 'Select subject to load' self.subjectsButton.setEnabled(False) subjectsLayout = qt.QFormLayout(self.subjectsButton) self.layout.addWidget(self.subjectsButton) self.subjectsComboBox = qt.QComboBox() self.subjectsComboBox.addItem('Select subject ID') self.subjectsComboBox.currentIndexChanged.connect( self.onSubjectsComboBox) subjectsLayout.addWidget(self.subjectsComboBox) self.previousSubjectPushButton = qt.QPushButton('Previous') self.previousSubjectPushButton.clicked.connect( self.onPreviousSubjectButton) subjectsLayout.addWidget(self.previousSubjectPushButton) self.nextSubjectPushButton = qt.QPushButton('Next') self.nextSubjectPushButton.clicked.connect(self.onNextSubjectButton) subjectsLayout.addWidget(self.nextSubjectPushButton) self.layout.addStretch()
def setup(self): self.setLayout(qt.QGridLayout()) settingNames = self.getSettingNames() for index, setting in enumerate(settingNames): label = self.createLabel(setting) value = self.getSetting(setting) if value.lower() in ["true", "false"]: element = qt.QCheckBox() element.checked = value.lower() == "true" elif value.isdigit(): element = qt.QSpinBox() element.value = int(value) elif os.path.exists(value): element = ctk.ctkPathLineEdit() if os.path.isdir(value): element.filters = ctk.ctkPathLineEdit.Dirs else: element.filters = ctk.ctkPathLineEdit.Files element.currentPath = value else: element = self.createLineEdit(value) element.minimumWidth = self.getMinimumTextWidth( element.text) + 10 self.layout().addWidget(label, index, 0) self.layout().addWidget(element, index, 1, 1, qt.QSizePolicy.ExpandFlag) self.keyElementPairs.append((label.text, element)) self.okButton = self.createButton("OK") self.cancelButton = self.createButton("Cancel") self.addButton(self.okButton, qt.QMessageBox.AcceptRole) self.addButton(self.cancelButton, qt.QMessageBox.NoRole) self.layout().addWidget( self.createHLayout([self.okButton, self.cancelButton]), len(settingNames), 1) self.okButton.clicked.connect(self.onOkButtonClicked)
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): self.CsvInputGroupBox = qt.QGroupBox('CSV input for local files') CsvInputLayout = qt.QFormLayout(self.CsvInputGroupBox) # # Input CSV Path # self.batchTableSelector = slicer.qMRMLNodeComboBox() self.batchTableSelector.nodeTypes = ['vtkMRMLTableNode'] self.batchTableSelector.addEnabled = True self.batchTableSelector.selectNodeUponCreation = True self.batchTableSelector.renameEnabled = True self.batchTableSelector.removeEnabled = True self.batchTableSelector.noneEnabled = False self.batchTableSelector.setMRMLScene(slicer.mrmlScene) self.batchTableSelector.toolTip = 'Select the table representing the cases to process.' CsvInputLayout.addRow(self.batchTableSelector) # # Parameters Area # self.parametersCollapsibleButton = ctk.ctkCollapsibleButton() self.parametersCollapsibleButton.text = 'Table view and attribute properties' CsvInputLayout.addWidget(self.parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(self.parametersCollapsibleButton) self.batchTableView = slicer.qMRMLTableView() parametersFormLayout.addRow(self.batchTableView) self.batchTableView.show() # # Input parameters GroupBox # self.inputParametersGroupBox = qt.QGroupBox('Input parameters') parametersFormLayout.addRow(self.inputParametersGroupBox) inputParametersFormLayout = qt.QFormLayout(self.inputParametersGroupBox) # # Root Path # self.rootSelector = qt.QLineEdit() self.rootSelector.text = 'path' self.rootSelector.toolTip = 'Location of the root directory to load from, or the column name specifying said ' \ 'directory in the input CSV' inputParametersFormLayout.addRow('Root Column', self.rootSelector) # # Image Path # self.imageSelector = qt.QLineEdit() self.imageSelector.text = 'image' self.imageSelector.toolTip = 'Name of the column specifying main image files in input CSV' inputParametersFormLayout.addRow('Image Column', self.imageSelector) # # GroundTruth masks # self.inputGTMaskColumnNames = qt.QLineEdit() self.inputGTMaskColumnNames.text = 'gt_0,gt_1,gt_2' self.inputGTMaskColumnNames.toolTip = 'Comma separated names of the columns specifying groundtruth mask files in input CSV' inputParametersFormLayout.addRow('Groundtruth masks Column(s)', self.inputGTMaskColumnNames) # # Predicted masks # self.inputPredMaskColumnNames = qt.QLineEdit() self.inputPredMaskColumnNames.text = 'pred_0,pred_1,pred_2' self.inputPredMaskColumnNames.toolTip = 'Comma separated names of the columns specifying predicted mask files in input CSV' inputParametersFormLayout.addRow('Predicted masks Column(s)', self.inputPredMaskColumnNames) self.iterationParametersGroupBox = qt.QGroupBox('Iteration parameters') parametersFormLayout.addRow(self.iterationParametersGroupBox) iterationParametersFormLayout = qt.QFormLayout(self.iterationParametersGroupBox) # # Cache Cases # self.cacheCases = qt.QCheckBox() self.cacheCases.checked = True self.cacheCases.toolTip = 'Cache cases for faster reload' iterationParametersFormLayout.addRow('Cache cases', self.cacheCases) # # Preload Cases # self.preloadCases = qt.QCheckBox() self.preloadCases.checked = False self.preloadCases.toolTip = 'Preloading all cases' iterationParametersFormLayout.addRow('Preload cases', self.preloadCases) # # Output Case Table Directory # self.tableOutputDirectory = ctk.ctkPathLineEdit() self.tableOutputDirectory.filters = ctk.ctkPathLineEdit.Dirs iterationParametersFormLayout.addRow('Case tables output dir', self.tableOutputDirectory) # # Progressbar # self.progressBar = qt.QProgressBar() self.progressBar.setFormat("%v/%m") self.progressBar.visible = False iterationParametersFormLayout.addWidget(self.progressBar) # # Connect Event Handlers # self.batchTableSelector.connect('nodeActivated(vtkMRMLNode*)', self.onChangeTable) self.imageSelector.connect('textEdited(QString)', self.onChangeImageColumn) self.preloadCases.stateChanged.connect(self.onPreloadCasesChanged) return self.CsvInputGroupBox
def setup(self): ScriptedLoadableModuleWidget.setup(self) self.logic = ScreenCaptureLogic() self.logic.logCallback = self.addLog # Instantiate and connect widgets ... # # Input area # inputCollapsibleButton = ctk.ctkCollapsibleButton() inputCollapsibleButton.text = "Input" self.layout.addWidget(inputCollapsibleButton) inputFormLayout = qt.QFormLayout(inputCollapsibleButton) # Input view selector self.viewNodeSelector = slicer.qMRMLNodeComboBox() self.viewNodeSelector.nodeTypes = ["vtkMRMLSliceNode", "vtkMRMLViewNode"] self.viewNodeSelector.addEnabled = False self.viewNodeSelector.removeEnabled = False self.viewNodeSelector.noneEnabled = False self.viewNodeSelector.showHidden = False self.viewNodeSelector.showChildNodeTypes = False self.viewNodeSelector.setMRMLScene( slicer.mrmlScene ) self.viewNodeSelector.setToolTip( "Contents of this slice or 3D view will be captured." ) inputFormLayout.addRow("View to capture: ", self.viewNodeSelector) # # Slice view options area # self.sliceViewOptionsCollapsibleButton = ctk.ctkCollapsibleButton() self.sliceViewOptionsCollapsibleButton.text = "Slice viewer sweep" self.layout.addWidget(self.sliceViewOptionsCollapsibleButton) sliceViewOptionsLayout = qt.QFormLayout(self.sliceViewOptionsCollapsibleButton) # Start slice offset position self.startSliceOffsetSliderWidget = ctk.ctkSliderWidget() self.startSliceOffsetSliderWidget.singleStep = 30 self.startSliceOffsetSliderWidget.minimum = -100 self.startSliceOffsetSliderWidget.maximum = 100 self.startSliceOffsetSliderWidget.value = 0 self.startSliceOffsetSliderWidget.setToolTip("Start slice offset.") sliceViewOptionsLayout.addRow("Start offset:", self.startSliceOffsetSliderWidget) # End slice offset position self.endSliceOffsetSliderWidget = ctk.ctkSliderWidget() self.endSliceOffsetSliderWidget.singleStep = 5 self.endSliceOffsetSliderWidget.minimum = -100 self.endSliceOffsetSliderWidget.maximum = 100 self.endSliceOffsetSliderWidget.value = 0 self.endSliceOffsetSliderWidget.setToolTip("End slice offset.") sliceViewOptionsLayout.addRow("End offset:", self.endSliceOffsetSliderWidget) # # 3D view options area # self.threeDViewOptionsCollapsibleButton = ctk.ctkCollapsibleButton() self.threeDViewOptionsCollapsibleButton.text = "3D view rotation" self.layout.addWidget(self.threeDViewOptionsCollapsibleButton) threeDViewOptionsLayout = qt.QFormLayout(self.threeDViewOptionsCollapsibleButton) # Start rotation self.startRotationSliderWidget = ctk.ctkSliderWidget() self.startRotationSliderWidget.singleStep = 5 self.startRotationSliderWidget.minimum = 0 self.startRotationSliderWidget.maximum = 180 self.startRotationSliderWidget.value = 180 self.startRotationSliderWidget.setToolTip("Rotation angle for the first image, relative to current orientation.") threeDViewOptionsLayout.addRow("Start rotation angle:", self.startRotationSliderWidget) # End rotation self.endRotationSliderWidget = ctk.ctkSliderWidget() self.endRotationSliderWidget.singleStep = 5 self.endRotationSliderWidget.minimum = 0 self.endRotationSliderWidget.maximum = 180 self.endRotationSliderWidget.value = 180 self.endRotationSliderWidget.setToolTip("Rotation angle for the last image, relative to current orientation.") threeDViewOptionsLayout.addRow("End rotation angle:", self.endRotationSliderWidget) # # Output area # outputCollapsibleButton = ctk.ctkCollapsibleButton() outputCollapsibleButton.text = "Output" self.layout.addWidget(outputCollapsibleButton) outputFormLayout = qt.QFormLayout(outputCollapsibleButton) # Number of steps value self.numberOfStepsSliderWidget = ctk.ctkSliderWidget() self.numberOfStepsSliderWidget.singleStep = 5 self.numberOfStepsSliderWidget.minimum = 2 self.numberOfStepsSliderWidget.maximum = 150 self.numberOfStepsSliderWidget.value = 30 self.numberOfStepsSliderWidget.decimals = 0 self.numberOfStepsSliderWidget.setToolTip("Number of images extracted between start and stop positions.") outputFormLayout.addRow("Number of images:", self.numberOfStepsSliderWidget) # Output directory selector self.outputDirSelector = ctk.ctkPathLineEdit() self.outputDirSelector.filters = ctk.ctkPathLineEdit.Dirs self.outputDirSelector.settingKey = 'ScreenCaptureOutputDir' outputFormLayout.addRow("Output directory:", self.outputDirSelector) if not self.outputDirSelector.currentPath: defaultOutputPath = os.path.abspath(os.path.join(slicer.app.defaultScenePath,'SlicerCapture')) self.outputDirSelector.setCurrentPath(defaultOutputPath) self.videoExportCheckBox = qt.QCheckBox() self.videoExportCheckBox.checked = False self.videoExportCheckBox.setToolTip("If checked, exported images will be written as a video file.") outputFormLayout.addRow("Video export:", self.videoExportCheckBox) self.videoFileNameWidget = qt.QLineEdit() self.videoFileNameWidget.setToolTip("String that defines file name, type, and numbering scheme. Default: capture.avi.") self.videoFileNameWidget.text = "SlicerCapture.avi" self.videoFileNameWidget.setEnabled(False) outputFormLayout.addRow("Video file name:", self.videoFileNameWidget) self.videoQualitySliderWidget = ctk.ctkSliderWidget() self.videoQualitySliderWidget.singleStep = 0.1 self.videoQualitySliderWidget.minimum = 0 self.videoQualitySliderWidget.maximum = 20 self.videoQualitySliderWidget.value = 2 self.videoQualitySliderWidget.decimals = 1 self.videoQualitySliderWidget.setToolTip("Bit-rate of video. Higher value means higher quality and larger file size.") outputFormLayout.addRow("Video quality:", self.videoQualitySliderWidget) self.videoFrameRateSliderWidget = ctk.ctkSliderWidget() self.videoFrameRateSliderWidget.singleStep = 0.1 self.videoFrameRateSliderWidget.minimum = 0.1 self.videoFrameRateSliderWidget.maximum = 60 self.videoFrameRateSliderWidget.value = 25 self.videoFrameRateSliderWidget.decimals = 0 self.videoFrameRateSliderWidget.setToolTip("Frames per second. Higher values mean faster, shorter videos.") outputFormLayout.addRow("Frame rate:", self.videoFrameRateSliderWidget) # Capture button self.captureButton = qt.QPushButton("Capture") self.captureButton.toolTip = "Capture slice sweep to image sequence." outputFormLayout.addRow(self.captureButton) self.statusLabel = qt.QPlainTextEdit() self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse) self.statusLabel.setCenterOnScroll(True) outputFormLayout.addRow(self.statusLabel) # # Advanced area # self.advancedCollapsibleButton = ctk.ctkCollapsibleButton() self.advancedCollapsibleButton.text = "Advanced" self.advancedCollapsibleButton.collapsed = (self.logic.getFfmpegPath() is not None) self.layout.addWidget(self.advancedCollapsibleButton) advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton) self.fileNamePatternWidget = qt.QLineEdit() self.fileNamePatternWidget.setToolTip("String that defines file name, type, and numbering scheme. Default: image%05d.png.") self.fileNamePatternWidget.text = "image_%05d.png" advancedFormLayout.addRow("Image file name pattern:", self.fileNamePatternWidget) ffmpegPath = self.logic.getFfmpegPath() self.ffmpegPathSelector = ctk.ctkPathLineEdit() self.ffmpegPathSelector.setCurrentPath(ffmpegPath) self.ffmpegPathSelector.nameFilters = ['ffmpeg.exe', 'ffmpeg'] self.ffmpegPathSelector.setMaximumWidth(300) self.ffmpegPathSelector.setToolTip("Set the path to ffmpeg executable. Download from: https://www.ffmpeg.org/") self.ffmpegPathSelector.setEnabled(False) advancedFormLayout.addRow("ffmpeg executable:", self.ffmpegPathSelector) # Add vertical spacer self.layout.addStretch(1) # connections self.captureButton.connect('clicked(bool)', self.onCaptureButton) self.viewNodeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onViewNodeSelected) self.startSliceOffsetSliderWidget.connect('valueChanged(double)', self.setSliceOffset) self.endSliceOffsetSliderWidget.connect('valueChanged(double)', self.setSliceOffset) self.videoExportCheckBox.connect('toggled(bool)', self.fileNamePatternWidget, 'setDisabled(bool)') self.videoExportCheckBox.connect('toggled(bool)', self.ffmpegPathSelector, 'setEnabled(bool)') self.videoExportCheckBox.connect('toggled(bool)', self.videoFileNameWidget, 'setEnabled(bool)') self.onViewNodeSelected()
def setup(self): ScriptedLoadableModuleWidget.setup(self) self.logic = ScreenCaptureLogic() self.logic.logCallback = self.addLog self.viewNodeType = None self.animationMode = None # Instantiate and connect widgets ... # # Input area # inputCollapsibleButton = ctk.ctkCollapsibleButton() inputCollapsibleButton.text = "Input" self.layout.addWidget(inputCollapsibleButton) inputFormLayout = qt.QFormLayout(inputCollapsibleButton) # Input view selector self.viewNodeSelector = slicer.qMRMLNodeComboBox() self.viewNodeSelector.nodeTypes = ["vtkMRMLSliceNode", "vtkMRMLViewNode"] self.viewNodeSelector.addEnabled = False self.viewNodeSelector.removeEnabled = False self.viewNodeSelector.noneEnabled = False self.viewNodeSelector.showHidden = False self.viewNodeSelector.showChildNodeTypes = False self.viewNodeSelector.setMRMLScene( slicer.mrmlScene ) self.viewNodeSelector.setToolTip( "Contents of this slice or 3D view will be captured." ) inputFormLayout.addRow("View to capture: ", self.viewNodeSelector) # Mode self.animationModeWidget = qt.QComboBox() self.animationModeWidget.setToolTip("Select the property that will be adjusted") inputFormLayout.addRow("Animation mode:", self.animationModeWidget) # Slice start offset position self.sliceStartOffsetSliderLabel = qt.QLabel("Start sweep offset:") self.sliceStartOffsetSliderWidget = ctk.ctkSliderWidget() self.sliceStartOffsetSliderWidget.singleStep = 30 self.sliceStartOffsetSliderWidget.minimum = -100 self.sliceStartOffsetSliderWidget.maximum = 100 self.sliceStartOffsetSliderWidget.value = 0 self.sliceStartOffsetSliderWidget.setToolTip("Start slice sweep offset.") inputFormLayout.addRow(self.sliceStartOffsetSliderLabel, self.sliceStartOffsetSliderWidget) # Slice end offset position self.sliceEndOffsetSliderLabel = qt.QLabel("End sweep offset:") self.sliceEndOffsetSliderWidget = ctk.ctkSliderWidget() self.sliceEndOffsetSliderWidget.singleStep = 5 self.sliceEndOffsetSliderWidget.minimum = -100 self.sliceEndOffsetSliderWidget.maximum = 100 self.sliceEndOffsetSliderWidget.value = 0 self.sliceEndOffsetSliderWidget.setToolTip("End slice sweep offset.") inputFormLayout.addRow(self.sliceEndOffsetSliderLabel, self.sliceEndOffsetSliderWidget) # 3D start rotation self.startRotationSliderLabel = qt.QLabel("Start rotation angle:") self.startRotationSliderWidget = ctk.ctkSliderWidget() self.startRotationSliderWidget.singleStep = 5 self.startRotationSliderWidget.minimum = 0 self.startRotationSliderWidget.maximum = 180 self.startRotationSliderWidget.value = 180 self.startRotationSliderWidget.setToolTip("Rotation angle for the first image, relative to current orientation.") inputFormLayout.addRow(self.startRotationSliderLabel, self.startRotationSliderWidget) # 3D end rotation self.endRotationSliderLabel = qt.QLabel("End rotation angle:") self.endRotationSliderWidget = ctk.ctkSliderWidget() self.endRotationSliderWidget.singleStep = 5 self.endRotationSliderWidget.minimum = 0 self.endRotationSliderWidget.maximum = 180 self.endRotationSliderWidget.value = 180 self.endRotationSliderWidget.setToolTip("Rotation angle for the last image, relative to current orientation.") inputFormLayout.addRow(self.endRotationSliderLabel, self.endRotationSliderWidget) # Sequence browser node selector self.sequenceBrowserNodeSelectorLabel = qt.QLabel("End rotation angle:") self.sequenceBrowserNodeSelectorWidget = slicer.qMRMLNodeComboBox() self.sequenceBrowserNodeSelectorWidget.nodeTypes = ["vtkMRMLSequenceBrowserNode"] self.sequenceBrowserNodeSelectorWidget.addEnabled = False self.sequenceBrowserNodeSelectorWidget.removeEnabled = False self.sequenceBrowserNodeSelectorWidget.noneEnabled = False self.sequenceBrowserNodeSelectorWidget.showHidden = False self.sequenceBrowserNodeSelectorWidget.setMRMLScene( slicer.mrmlScene ) self.sequenceBrowserNodeSelectorWidget.setToolTip( "Items defined by this sequence browser will be replayed." ) inputFormLayout.addRow(self.sequenceBrowserNodeSelectorLabel, self.sequenceBrowserNodeSelectorWidget) # Sequence start index self.sequenceStartItemIndexLabel = qt.QLabel("Start index:") self.sequenceStartItemIndexWidget = ctk.ctkSliderWidget() self.sequenceStartItemIndexWidget.minimum = 0 self.sequenceStartItemIndexWidget.decimals = 0 self.sequenceStartItemIndexWidget.setToolTip("First item in the sequence to capture.") inputFormLayout.addRow(self.sequenceStartItemIndexLabel, self.sequenceStartItemIndexWidget) # Sequence end index self.sequenceEndItemIndexLabel = qt.QLabel("End index:") self.sequenceEndItemIndexWidget = ctk.ctkSliderWidget() self.sequenceEndItemIndexWidget.singleStep = 10 self.sequenceEndItemIndexWidget.minimum = 0 self.sequenceEndItemIndexWidget.decimals = 0 self.sequenceEndItemIndexWidget.setToolTip("Last item in the sequence to capture.") inputFormLayout.addRow(self.sequenceEndItemIndexLabel, self.sequenceEndItemIndexWidget) # # Output area # outputCollapsibleButton = ctk.ctkCollapsibleButton() outputCollapsibleButton.text = "Output" self.layout.addWidget(outputCollapsibleButton) outputFormLayout = qt.QFormLayout(outputCollapsibleButton) # Number of steps value self.numberOfStepsSliderWidget = ctk.ctkSliderWidget() self.numberOfStepsSliderWidget.singleStep = 10 self.numberOfStepsSliderWidget.minimum = 2 self.numberOfStepsSliderWidget.maximum = 150 self.numberOfStepsSliderWidget.value = 31 self.numberOfStepsSliderWidget.decimals = 0 self.numberOfStepsSliderWidget.setToolTip("Number of images extracted between start and stop positions.") outputFormLayout.addRow("Number of images:", self.numberOfStepsSliderWidget) # Output directory selector self.outputDirSelector = ctk.ctkPathLineEdit() self.outputDirSelector.filters = ctk.ctkPathLineEdit.Dirs self.outputDirSelector.settingKey = 'ScreenCaptureOutputDir' outputFormLayout.addRow("Output directory:", self.outputDirSelector) if not self.outputDirSelector.currentPath: defaultOutputPath = os.path.abspath(os.path.join(slicer.app.defaultScenePath,'SlicerCapture')) self.outputDirSelector.setCurrentPath(defaultOutputPath) self.videoExportCheckBox = qt.QCheckBox() self.videoExportCheckBox.checked = False self.videoExportCheckBox.setToolTip("If checked, exported images will be written as a video file." " Requires setting of ffmpeg executable path in Advanced section.") outputFormLayout.addRow("Video export:", self.videoExportCheckBox) self.videoFileNameWidget = qt.QLineEdit() self.videoFileNameWidget.setToolTip("String that defines file name, type, and numbering scheme. Default: capture.avi.") self.videoFileNameWidget.text = "SlicerCapture.avi" self.videoFileNameWidget.setEnabled(False) outputFormLayout.addRow("Video file name:", self.videoFileNameWidget) self.videoLengthSliderWidget = ctk.ctkSliderWidget() self.videoLengthSliderWidget.singleStep = 0.1 self.videoLengthSliderWidget.minimum = 0.1 self.videoLengthSliderWidget.maximum = 30 self.videoLengthSliderWidget.value = 5 self.videoLengthSliderWidget.suffix = "s" self.videoLengthSliderWidget.decimals = 1 self.videoLengthSliderWidget.setToolTip("Length of the exported video in seconds.") self.videoLengthSliderWidget.setEnabled(False) outputFormLayout.addRow("Video length:", self.videoLengthSliderWidget) # # Advanced area # self.advancedCollapsibleButton = ctk.ctkCollapsibleButton() self.advancedCollapsibleButton.text = "Advanced" self.advancedCollapsibleButton.collapsed = True outputFormLayout.addRow(self.advancedCollapsibleButton) advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton) self.fileNamePatternWidget = qt.QLineEdit() self.fileNamePatternWidget.setToolTip( "String that defines file name, type, and numbering scheme. Default: image%05d.png.") self.fileNamePatternWidget.text = "image_%05d.png" advancedFormLayout.addRow("Image file name pattern:", self.fileNamePatternWidget) ffmpegPath = self.logic.getFfmpegPath() self.ffmpegPathSelector = ctk.ctkPathLineEdit() self.ffmpegPathSelector.setCurrentPath(ffmpegPath) self.ffmpegPathSelector.nameFilters = ['ffmpeg.exe', 'ffmpeg'] self.ffmpegPathSelector.setMaximumWidth(300) self.ffmpegPathSelector.setToolTip("Set the path to ffmpeg executable. Download from: https://www.ffmpeg.org/") advancedFormLayout.addRow("ffmpeg executable:", self.ffmpegPathSelector) self.extraVideoOptionsWidget = qt.QComboBox() self.extraVideoOptionsWidget.addItem("-c:v mpeg4 -qscale:v 5") self.extraVideoOptionsWidget.addItem("-c:v libx264 -preset veryslow -qp 0") self.extraVideoOptionsWidget.addItem("-f mp4 -vcodec libx264 -pix_fmt yuv420p") self.extraVideoOptionsWidget.setEditable(True) self.extraVideoOptionsWidget.setToolTip( '<html>\n' ' <p>Additional video conversion options passed to ffmpeg.</p>' ' <p><b>Examples:</b>' ' <ul>' ' <li><b>MPEG4: </b>-c:v mpeg4 -qscale:v 5</li>' ' <li><b>H264: </b>-c:v libx264 -preset veryslow -qp 0</li>' ' <li><b>Quicktime: </b>-f mp4 -vcodec libx264 -pix_fmt yuv420p</li>' ' </ul></p>' ' <p>See more encoding options at:' ' <i>https://trac.ffmpeg.org/wiki/Encode/H.264</i> and' ' <i>https://trac.ffmpeg.org/wiki/Encode/MPEG-4</i></p>' '</html>') advancedFormLayout.addRow("Video extra options:", self.extraVideoOptionsWidget) # Capture button self.captureButton = qt.QPushButton("Capture") self.captureButton.toolTip = "Capture slice sweep to image sequence." outputFormLayout.addRow(self.captureButton) self.statusLabel = qt.QPlainTextEdit() self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse) self.statusLabel.setCenterOnScroll(True) outputFormLayout.addRow(self.statusLabel) # # Add vertical spacer #self.layout.addStretch(1) # connections self.captureButton.connect('clicked(bool)', self.onCaptureButton) self.viewNodeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.updateViewOptions) self.animationModeWidget.connect("currentIndexChanged(int)", self.updateViewOptions) self.sliceStartOffsetSliderWidget.connect('valueChanged(double)', self.setSliceOffset) self.sliceEndOffsetSliderWidget.connect('valueChanged(double)', self.setSliceOffset) self.sequenceBrowserNodeSelectorWidget.connect("currentNodeChanged(vtkMRMLNode*)", self.updateViewOptions) self.sequenceStartItemIndexWidget.connect('valueChanged(double)', self.setSequenceItemIndex) self.sequenceEndItemIndexWidget.connect('valueChanged(double)', self.setSequenceItemIndex) self.videoExportCheckBox.connect('toggled(bool)', self.fileNamePatternWidget, 'setDisabled(bool)') self.videoExportCheckBox.connect('toggled(bool)', self.videoFileNameWidget, 'setEnabled(bool)') self.videoExportCheckBox.connect('toggled(bool)', self.videoLengthSliderWidget, 'setEnabled(bool)') self.updateViewOptions()
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... self.dockerGroupBox = ctk.ctkCollapsibleGroupBox() self.dockerGroupBox.setTitle('Docker Settings') self.layout.addWidget(self.dockerGroupBox) dockerForm = qt.QFormLayout(self.dockerGroupBox) self.dockerPath = ctk.ctkPathLineEdit() # self.dockerPath.setMaximumWidth(300) if platform.system() == 'Darwin': self.dockerPath.setCurrentPath('/usr/local/bin/docker') if platform.system() == 'Linux': self.dockerPath.setCurrentPath('/usr/bin/docker') if platform.system() == 'Windows': self.dockerPath.setCurrentPath( "C:/Program Files/Docker/Docker/resources/bin/docker.exe") ### use nvidia-docker if it is installed nvidiaDockerPath = self.dockerPath.currentPath.replace( 'bin/docker', 'bin/nvidia-docker') if os.path.isfile(nvidiaDockerPath): self.dockerPath.setCurrentPath(nvidiaDockerPath) self.downloadButton = qt.QPushButton('Download') self.downloadButton.connect('clicked(bool)', self.onDownloadButton) dockerForm.addRow("Docker Executable Path:", self.dockerPath) dockerForm.addRow("Download the docker image:", self.downloadButton) self.progressDownload = qt.QProgressBar() self.progressDownload.setRange(0, 100) self.progressDownload.setValue(0) self.progressDownload.hide() self.dockerVolumePath = ctk.ctkPathLineEdit() defaultVolumePath = os.path.join(expanduser("~"), ".dockerVolume") if not os.path.exists(defaultVolumePath): os.makedirs(defaultVolumePath) self.dockerVolumePath.setCurrentPath(defaultVolumePath) dockerForm.addRow("Docker Volume Directory:", self.dockerVolumePath) # # 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.inputVolumeSelector = slicer.qMRMLNodeComboBox() self.inputVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] self.inputVolumeSelector.selectNodeUponCreation = True self.inputVolumeSelector.addEnabled = False self.inputVolumeSelector.removeEnabled = False self.inputVolumeSelector.noneEnabled = False self.inputVolumeSelector.showHidden = False self.inputVolumeSelector.showChildNodeTypes = False self.inputVolumeSelector.setMRMLScene(slicer.mrmlScene) self.inputVolumeSelector.setCurrentNode(None) self.inputVolumeSelector.setToolTip("Pick the input to the algorithm.") parametersFormLayout.addRow("Input Volume: ", self.inputVolumeSelector) # # Apply Button # self.applyButton = qt.QPushButton("Generate Probablity Map") self.applyButton.toolTip = "Generate the probablity map." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # # output vessel model selector # self.outputModelSelector = slicer.qMRMLNodeComboBox() self.outputModelSelector.nodeTypes = ["vtkMRMLModelNode"] self.outputModelSelector.selectNodeUponCreation = True self.outputModelSelector.addEnabled = True self.outputModelSelector.removeEnabled = True self.outputModelSelector.noneEnabled = True self.outputModelSelector.showHidden = False self.outputModelSelector.showChildNodeTypes = False self.outputModelSelector.setMRMLScene(slicer.mrmlScene) self.outputModelSelector.setToolTip( "Pick the output to the algorithm.") parametersFormLayout.addRow("Output vessel model: ", self.outputModelSelector) # # threshold value # self.imageThresholdSliderWidget = ctk.ctkSliderWidget() self.imageThresholdSliderWidget.singleStep = 0.01 self.imageThresholdSliderWidget.minimum = 0.5 self.imageThresholdSliderWidget.maximum = 1.0 self.imageThresholdSliderWidget.value = 0.9 self.imageThresholdSliderWidget.setToolTip( "Set threshold value for computing the output image. Voxels that have intensities lower than this value will set to zero." ) parametersFormLayout.addRow("Image threshold", self.imageThresholdSliderWidget) self.createVesselModelButton = qt.QPushButton("Create Vessel Model") self.createVesselModelButton.toolTip = "Generate the vessel model." self.createVesselModelButton.enabled = False parametersFormLayout.addRow(self.createVesselModelButton) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.createVesselModelButton.connect('clicked(bool)', self.onCreateModelWithThreshold) self.inputVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelectVolume) self.outputModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelectModel) # Add vertical spacer self.layout.addStretch(1) self.logic = DockerVesselSegLogic()
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) # # Select base mesh # self.modelSelector = slicer.qMRMLNodeComboBox() self.modelSelector.nodeTypes = (("vtkMRMLModelNode"), "") self.modelSelector.selectNodeUponCreation = False self.modelSelector.addEnabled = False self.modelSelector.removeEnabled = False self.modelSelector.noneEnabled = True self.modelSelector.showHidden = False self.modelSelector.setMRMLScene(slicer.mrmlScene) parametersFormLayout.addRow("Base mesh: ", self.modelSelector) # # Select base landmark file # #self.baseLMFile=ctk.ctkPathLineEdit() #self.baseLMFile.setToolTip( "Select file specifying base landmarks" ) #parametersFormLayout.addRow("Base landmark file: ", self.baseLMFile) self.baseLMSelect = slicer.qMRMLNodeComboBox() self.baseLMSelect.nodeTypes = (('vtkMRMLMarkupsFiducialNode'), "") self.baseLMSelect.selectNodeUponCreation = False self.baseLMSelect.addEnabled = False self.baseLMSelect.removeEnabled = False self.baseLMSelect.noneEnabled = True self.baseLMSelect.showHidden = False self.baseLMSelect.showChildNodeTypes = False self.baseLMSelect.setMRMLScene(slicer.mrmlScene) parametersFormLayout.addRow("Base landmarks: ", self.baseLMSelect) # # Select base semi-landmark file # #self.semiLMFile=ctk.ctkPathLineEdit() #self.semiLMFile.setToolTip( "Select file containing base semi-landmarks " ) #parametersFormLayout.addRow("Base semi-landmark file: ", self.semiLMFile) self.baseSLMSelect = slicer.qMRMLNodeComboBox() self.baseSLMSelect.nodeTypes = (('vtkMRMLMarkupsFiducialNode'), "") self.baseSLMSelect.selectNodeUponCreation = False self.baseSLMSelect.addEnabled = False self.baseSLMSelect.removeEnabled = False self.baseSLMSelect.noneEnabled = True self.baseSLMSelect.showHidden = False self.baseSLMSelect.showChildNodeTypes = False self.baseSLMSelect.setMRMLScene(slicer.mrmlScene) parametersFormLayout.addRow("Base semi-landmarks: ", self.baseSLMSelect) # # Select meshes directory # self.meshDirectory = ctk.ctkPathLineEdit() self.meshDirectory.filters = ctk.ctkPathLineEdit.Dirs self.meshDirectory.setToolTip("Select directory containing meshes") parametersFormLayout.addRow("Mesh directory: ", self.meshDirectory) # # Select landmarks directory # self.landmarkDirectory = ctk.ctkPathLineEdit() self.landmarkDirectory.filters = ctk.ctkPathLineEdit.Dirs self.landmarkDirectory.setToolTip( "Select directory containing landmarks") parametersFormLayout.addRow("Landmark directory: ", self.landmarkDirectory) # # Select output directory # self.outputDirectory = ctk.ctkPathLineEdit() self.outputDirectory.filters = ctk.ctkPathLineEdit.Dirs self.outputDirectory.setToolTip("Select directory for output models: ") parametersFormLayout.addRow("Output directory: ", self.outputDirectory) # # Set projection scale # self.scaleProjection = ctk.ctkSliderWidget() self.scaleProjection.singleStep = 1 self.scaleProjection.minimum = 0 self.scaleProjection.maximum = 100 self.scaleProjection.value = 10 self.scaleProjection.setToolTip( "Set scale of maximum point projection") parametersFormLayout.addRow("Projection scale: ", self.scaleProjection) # # Select output extension # self.JSONType = qt.QRadioButton() self.JSONType.setChecked(True) parametersFormLayout.addRow("MRK.JSON output: ", self.JSONType) self.FCSVType = qt.QRadioButton() parametersFormLayout.addRow("FCSV output: ", self.FCSVType) # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Generate ProjectSemiLMs." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # connections self.modelSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onSelect) self.baseLMSelect.connect('currentNodeChanged(vtkMRMLNode*)', self.onSelect) self.baseSLMSelect.connect('currentNodeChanged(vtkMRMLNode*)', self.onSelect) self.meshDirectory.connect('validInputChanged(bool)', self.onSelect) self.landmarkDirectory.connect('validInputChanged(bool)', self.onSelect) self.outputDirectory.connect('validInputChanged(bool)', self.onSelect) self.applyButton.connect('clicked(bool)', self.onApplyButton) # Add vertical spacer self.layout.addStretch(1)
def _addCustomizationSection(self): customizationCollapsibleButton = ctk.ctkCollapsibleButton() customizationCollapsibleButton.text = 'Extraction Customization' customizationCollapsibleButton.collapsed = True self.layout.addWidget(customizationCollapsibleButton) customizationFormLayout = qt.QFormLayout(customizationCollapsibleButton) # # Radiobuttons to select customization Type # self.manualCustomizationRadioButton = qt.QRadioButton() self.manualCustomizationRadioButton.text = 'Manual Customization' self.manualCustomizationRadioButton.checked = True customizationFormLayout.layout().addWidget(self.manualCustomizationRadioButton) self.parameterFileCustomizationRadioButton = qt.QRadioButton() self.parameterFileCustomizationRadioButton.text = 'Parameter File Customization' self.parameterFileCustomizationRadioButton.checked = False customizationFormLayout.layout().addWidget(self.parameterFileCustomizationRadioButton) # # Manual Customization # self.manualCustomizationGroupBox = qt.QGroupBox('Manual Customization') self.manualCustomizationGroupBox.visible = True # self.manualCustomizationGroupBox.checkable = True customizationFormLayout.addWidget(self.manualCustomizationGroupBox) manualCustomizationFormLayout = qt.QFormLayout(self.manualCustomizationGroupBox) # Feature Class section featureClassCollapsibleButton = ctk.ctkCollapsibleButton() featureClassCollapsibleButton.text = 'Feature Classes' featureClassCollapsibleButton.collapsed = False manualCustomizationFormLayout.addWidget(featureClassCollapsibleButton) featureClassLayout = qt.QFormLayout(featureClassCollapsibleButton) self.featuresLayout = qt.QHBoxLayout() featureClassLayout.addRow('Features:', self.featuresLayout) self.featuresButtonGroup = qt.QButtonGroup(self.featuresLayout) self.featuresButtonGroup.exclusive = False # Get the feature classes dynamically self.features = list(getFeatureClasses().keys()) # Create a checkbox for each feature featureButtons = {} for feature in self.features: featureButtons[feature] = qt.QCheckBox(feature) # TODO: decide which features to enable by default featureButtons[feature].checked = False if feature == 'firstorder': featureButtons[feature].checked = True self.featuresButtonGroup.addButton(featureButtons[feature]) self.featuresLayout.layout().addWidget(featureButtons[feature]) # set the ID to be the index of this feature in the list self.featuresButtonGroup.setId(featureButtons[feature], self.features.index(feature)) # Add buttons to select all or none self.buttonsLayout = qt.QHBoxLayout() featureClassLayout.addRow('Toggle Features:', self.buttonsLayout) self.calculateAllFeaturesButton = qt.QPushButton('All Features') self.calculateAllFeaturesButton.toolTip = 'Calculate all feature classes.' self.calculateAllFeaturesButton.enabled = True self.buttonsLayout.addWidget(self.calculateAllFeaturesButton) self.calculateNoFeaturesButton = qt.QPushButton('No Features') self.calculateNoFeaturesButton.toolTip = 'Calculate no feature classes.' self.calculateNoFeaturesButton.enabled = True self.buttonsLayout.addWidget(self.calculateNoFeaturesButton) # Resampling and Filtering filteringCollapsibleButton = ctk.ctkCollapsibleButton() filteringCollapsibleButton.text = 'Resampling and Filtering' filteringCollapsibleButton.collapsed = False manualCustomizationFormLayout.addRow(filteringCollapsibleButton) # Layout within the dummy collapsible button filteringFormLayout = qt.QFormLayout(filteringCollapsibleButton) # Resampling self.resampledVoxelSize = qt.QLineEdit() self.resampledVoxelSize.toolTip = 'Three floating-point numbers separated by comma defining the resampled pixel ' \ 'size (mm).' filteringFormLayout.addRow('Resampled voxel size', self.resampledVoxelSize) # LoG kernel sizes. default to 5 (?) self.logKernelSizes = qt.QLineEdit() self.logKernelSizes.toolTip = 'Laplacian of Gaussian filter kernel sizes (mm), separated by comma. ' \ 'If empty, no LoG filtering will be applied.' filteringFormLayout.addRow('LoG kernel sizes', self.logKernelSizes) # Wavelet self.waveletCheckBox = qt.QCheckBox() self.waveletCheckBox.checked = 0 self.waveletCheckBox.toolTip = 'If checked, PyRadiomics will calculate features on the image after applying ' \ 'wavelet transformation' filteringFormLayout.addRow('Wavelet-based features', self.waveletCheckBox) # # Feature calculation settings # settingsCollapsibleButton = ctk.ctkCollapsibleButton() settingsCollapsibleButton.text = 'Settings' settingsCollapsibleButton.collapsed = False manualCustomizationFormLayout.addWidget(settingsCollapsibleButton) # Layout within the dummy collapsible button settingsFormLayout = qt.QFormLayout(settingsCollapsibleButton) # bin width, defaults to 25 self.binWidthSliderWidget = ctk.ctkSliderWidget() self.binWidthSliderWidget.singleStep = 1 self.binWidthSliderWidget.decimals = 2 self.binWidthSliderWidget.minimum = 0.01 self.binWidthSliderWidget.maximum = 100 self.binWidthSliderWidget.value = 25 self.binWidthSliderWidget.toolTip = 'Set the bin width' settingsFormLayout.addRow('Bin Width', self.binWidthSliderWidget) # symmetricalGLCM flag, defaults to false self.symmetricalGLCMCheckBox = qt.QCheckBox() self.symmetricalGLCMCheckBox.checked = 1 self.symmetricalGLCMCheckBox.toolTip = 'Use a symmetrical GLCM matrix' settingsFormLayout.addRow('Enforce Symmetrical GLCM', self.symmetricalGLCMCheckBox) # # Parameter File Customization # self.parameterCustomizationGroupBox = qt.QGroupBox('Parameter File Customization') self.parameterCustomizationGroupBox.visible = False # self.parameterCustomizationGroupBox.checkable = True customizationFormLayout.addWidget(self.parameterCustomizationGroupBox) parameterCustomizationFormLayout = qt.QFormLayout(self.parameterCustomizationGroupBox) # Path edit to select parameter file self.parameterFilePathLineEdit = ctk.ctkPathLineEdit() parameterCustomizationFormLayout.addRow("Parameter File", self.parameterFilePathLineEdit)
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) # # Select landmark file to import # self.inputDirectory = ctk.ctkPathLineEdit() self.inputDirectory.filters = ctk.ctkPathLineEdit.Dirs self.inputDirectory.setToolTip( "Select directory containing curves to resample") parametersFormLayout.addRow("Input Directory:", self.inputDirectory) # # output directory selector # self.outputDirectory = ctk.ctkPathLineEdit() self.outputDirectory.filters = ctk.ctkPathLineEdit.Dirs self.outputDirectory.currentPath = slicer.app.temporaryPath parametersFormLayout.addRow("Output Directory:", self.outputDirectory) # # Get Resample number # self.ResampleRateWidget = ctk.ctkDoubleSpinBox() self.ResampleRateWidget.value = 50 self.ResampleRateWidget.minimum = 3 self.ResampleRateWidget.maximum = 5000 self.ResampleRateWidget.singleStep = 1 self.ResampleRateWidget.setDecimals(0) self.ResampleRateWidget.setToolTip( "Select the number of points for resampling: ") parametersFormLayout.addRow("Output sample number: ", self.ResampleRateWidget) # # Get open or closed curve option # curveTypeSelector = qt.QHBoxLayout() self.curveTypeOpen = qt.QRadioButton("open") self.curveTypeOpen.setToolTip( "Select option for no interpolation between first and last points") self.curveTypeOpen.setChecked(True) self.curveTypeClosed = qt.QRadioButton("closed") self.curveTypeClosed.setToolTip( "Select option to interpolate between first and last points") curveTypeSelector.addWidget(self.curveTypeOpen) curveTypeSelector.addWidget(self.curveTypeClosed) curveTypeSelector.addStretch() parametersFormLayout.addRow("Curve Type: ", curveTypeSelector) # # 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 conversion." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.inputDirectory.connect('validInputChanged(bool)', self.onSelectInput) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelectInput()
def setup(self): self.logic = HerniaAnnotationModuleLogic() ScriptedLoadableModuleWidget.setup(self) self.detectionOn = False self.updateTimer = qt.QTimer() self.updateTimer.setInterval(100) self.updateTimer.setSingleShot(True) self.updateTimer.connect('timeout()', self.onUpdateTimer) # 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 = ["vtkMRMLStreamingVolumeNode"] 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) self.toolOneSelector = slicer.qMRMLNodeComboBox() self.toolOneSelector.nodeTypes = ["vtkMRMLLinearTransformNode"] self.toolOneSelector.selectNodeUponCreation = True self.toolOneSelector.addEnabled = False self.toolOneSelector.removeEnabled = False self.toolOneSelector.noneEnabled = False self.toolOneSelector.showHidden = False self.toolOneSelector.showChildNodeTypes = False self.toolOneSelector.setMRMLScene(slicer.mrmlScene) self.toolOneSelector.setToolTip("Pick the input to the algorithm.") parametersFormLayout.addRow("Input Tool One: ", self.toolOneSelector) self.toolTwoSelector = slicer.qMRMLNodeComboBox() self.toolTwoSelector.nodeTypes = ["vtkMRMLLinearTransformNode"] self.toolTwoSelector.selectNodeUponCreation = True self.toolTwoSelector.addEnabled = False self.toolTwoSelector.removeEnabled = False self.toolTwoSelector.noneEnabled = False self.toolTwoSelector.showHidden = False self.toolTwoSelector.showChildNodeTypes = False self.toolTwoSelector.setMRMLScene(slicer.mrmlScene) self.toolTwoSelector.setToolTip("Pick the input to the algorithm.") parametersFormLayout.addRow("Input Tool Two: ", self.toolTwoSelector) self.modelPathEdit = ctk.ctkPathLineEdit() parametersFormLayout.addRow("Keras model: ", self.modelPathEdit) # # threshold value # self.imageThresholdSliderWidget = ctk.ctkSliderWidget() self.imageThresholdSliderWidget.singleStep = 0.05 self.imageThresholdSliderWidget.minimum = 0 self.imageThresholdSliderWidget.maximum = 1.0 self.imageThresholdSliderWidget.value = 0.5 self.imageThresholdSliderWidget.setToolTip( "Set threshold value for class probability.") parametersFormLayout.addRow("Prediction threshold", self.imageThresholdSliderWidget) # # Apply Button # self.applyButton = qt.QPushButton("Start detection") self.applyButton.toolTip = "Run the algorithm." self.applyButton.enabled = True parametersFormLayout.addRow(self.applyButton) self.toolLabel = qt.QLabel("0") toolFont = self.toolLabel.font toolFont.setPointSize(32) self.toolLabel.setFont(toolFont) parametersFormLayout.addRow("Tool: ", self.toolLabel) self.classLabel = qt.QLabel("0") classFont = self.classLabel.font classFont.setPointSize(32) self.classLabel.setFont(classFont) parametersFormLayout.addRow("Tissue: ", self.classLabel) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) # Add vertical spacer self.layout.addStretch(1)
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) # # Select landmark file to import # self.inputFileSelector = ctk.ctkPathLineEdit() self.inputFileSelector.filters = ctk.ctkPathLineEdit().Files self.inputFileSelector.setToolTip("Select landmark file for import") parametersFormLayout.addRow( "Select file containing landmark names and coordinates to load:", self.inputFileSelector) # # output directory selector # self.outputDirectory = ctk.ctkDirectoryButton() self.outputDirectory.directory = slicer.mrmlScene.GetCacheManager( ).GetRemoteCacheDirectory() parametersFormLayout.addRow("Output Directory:", self.outputDirectory) # # Get header length # self.headerLengthWidget = ctk.ctkDoubleSpinBox() self.headerLengthWidget.value = 2 self.headerLengthWidget.minimum = 0 self.headerLengthWidget.singleStep = 1 self.headerLengthWidget.setToolTip( "Input the number of lines in header") parametersFormLayout.addRow("Header length:", self.headerLengthWidget) # # check box to trigger taking screen shots for later use in tutorials # self.loadLandmarkNode = qt.QCheckBox() self.loadLandmarkNode.checked = 0 self.loadLandmarkNode.setToolTip( "After conversion, load landmarks into the scene.") parametersFormLayout.addRow("Load landmarks into scene", self.loadLandmarkNode) # # 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.inputFileSelector.connect('validInputChanged(bool)', self.onSelect) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelect()
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Set up tabs to split workflow tabsWidget = qt.QTabWidget() alignSingleTab = qt.QWidget() alignSingleTabLayout = qt.QFormLayout(alignSingleTab) alignMultiTab = qt.QWidget() alignMultiTabLayout = qt.QFormLayout(alignMultiTab) tabsWidget.addTab(alignSingleTab, "Single Alignment") tabsWidget.addTab(alignMultiTab, "Batch processing") self.layout.addWidget(tabsWidget) # Layout within the tab alignSingleWidget = ctk.ctkCollapsibleButton() alignSingleWidgetLayout = qt.QFormLayout(alignSingleWidget) alignSingleWidget.text = "Align and subsample a source and reference mesh " alignSingleTabLayout.addRow(alignSingleWidget) # # Select source mesh # self.sourceModelSelector = ctk.ctkPathLineEdit() self.sourceModelSelector.filters = ctk.ctkPathLineEdit().Files self.sourceModelSelector.nameFilters = ["*.ply"] alignSingleWidgetLayout.addRow("Source mesh: ", self.sourceModelSelector) # # Select source landmarks # self.sourceFiducialSelector = ctk.ctkPathLineEdit() self.sourceFiducialSelector.filters = ctk.ctkPathLineEdit().Files self.sourceFiducialSelector.nameFilters = ["*.fcsv"] alignSingleWidgetLayout.addRow("Source landmarks: ", self.sourceFiducialSelector) # Select target mesh # self.targetModelSelector = ctk.ctkPathLineEdit() self.targetModelSelector.filters = ctk.ctkPathLineEdit().Files self.targetModelSelector.nameFilters = ["*.ply"] alignSingleWidgetLayout.addRow("Reference mesh: ", self.targetModelSelector) self.skipScalingCheckBox = qt.QCheckBox() self.skipScalingCheckBox.checked = 0 self.skipScalingCheckBox.setToolTip( "If checked, PointCloudRegistration will skip scaling during the alignment (Not recommended)." ) alignSingleWidgetLayout.addRow("Skip scaling", self.skipScalingCheckBox) [ self.pointDensity, self.normalSearchRadius, self.FPFHSearchRadius, self.distanceThreshold, self.maxRANSAC, self.maxRANSACValidation, self.ICPDistanceThreshold ] = self.addAdvancedMenu(alignSingleWidgetLayout) # Advanced tab connections self.pointDensity.connect('valueChanged(double)', self.onChangeAdvanced) self.normalSearchRadius.connect('valueChanged(double)', self.onChangeAdvanced) self.FPFHSearchRadius.connect('valueChanged(double)', self.onChangeAdvanced) self.distanceThreshold.connect('valueChanged(double)', self.onChangeAdvanced) self.maxRANSAC.connect('valueChanged(double)', self.onChangeAdvanced) self.maxRANSACValidation.connect('valueChanged(double)', self.onChangeAdvanced) self.ICPDistanceThreshold.connect('valueChanged(double)', self.onChangeAdvanced) # # Subsample Button # self.subsampleButton = qt.QPushButton("Run subsampling") self.subsampleButton.toolTip = "Run subsampling of the source and reference meshes" self.subsampleButton.enabled = False alignSingleWidgetLayout.addRow(self.subsampleButton) # # Subsample Information # self.subsampleInfo = qt.QPlainTextEdit() self.subsampleInfo.setPlaceholderText("Subsampling information") self.subsampleInfo.setReadOnly(True) alignSingleWidgetLayout.addRow(self.subsampleInfo) # # Align Button # self.alignButton = qt.QPushButton("Run rigid alignment") self.alignButton.toolTip = "Run rigid alignment of the source and reference meshes" self.alignButton.enabled = False alignSingleWidgetLayout.addRow(self.alignButton) # # Plot Aligned Mesh Button # self.displayMeshButton = qt.QPushButton("Display alignment") self.displayMeshButton.toolTip = "Display rigid alignment of the source and references meshes" self.displayMeshButton.enabled = False alignSingleWidgetLayout.addRow(self.displayMeshButton) # connections self.sourceModelSelector.connect('validInputChanged(bool)', self.onSelect) self.sourceFiducialSelector.connect('validInputChanged(bool)', self.onSelect) self.targetModelSelector.connect('validInputChanged(bool)', self.onSelect) self.subsampleButton.connect('clicked(bool)', self.onSubsampleButton) self.alignButton.connect('clicked(bool)', self.onAlignButton) self.displayMeshButton.connect('clicked(bool)', self.onDisplayMeshButton) # Layout within the multiprocessing tab alignMultiWidget = ctk.ctkCollapsibleButton() alignMultiWidgetLayout = qt.QFormLayout(alignMultiWidget) alignMultiWidget.text = "Alings landmarks from multiple specimens to a reference 3d model (mesh)" alignMultiTabLayout.addRow(alignMultiWidget) # # Select source mesh # self.sourceModelMultiSelector = ctk.ctkPathLineEdit() self.sourceModelMultiSelector.filters = ctk.ctkPathLineEdit.Dirs self.sourceModelMultiSelector.toolTip = "Select the directory containing the source meshes" alignMultiWidgetLayout.addRow("Source mesh directory: ", self.sourceModelMultiSelector) # # Select source landmark file # self.sourceFiducialMultiSelector = ctk.ctkPathLineEdit() self.sourceFiducialMultiSelector.filters = ctk.ctkPathLineEdit.Dirs self.sourceFiducialMultiSelector.toolTip = "Select the directory containing the source landmarks" alignMultiWidgetLayout.addRow("Source landmark directory: ", self.sourceFiducialMultiSelector) # Select target mesh directory # self.targetModelMultiSelector = ctk.ctkPathLineEdit() self.targetModelMultiSelector.filters = ctk.ctkPathLineEdit().Files self.targetModelMultiSelector.nameFilters = ["*.ply"] alignMultiWidgetLayout.addRow("Reference mesh: ", self.targetModelMultiSelector) # Select output landmark directory # self.landmarkOutputSelector = ctk.ctkPathLineEdit() self.landmarkOutputSelector.filters = ctk.ctkPathLineEdit.Dirs self.landmarkOutputSelector.toolTip = "Select the output directory where the landmarks will be saved" alignMultiWidgetLayout.addRow("Output landmark directory: ", self.landmarkOutputSelector) self.skipScalingMultiCheckBox = qt.QCheckBox() self.skipScalingMultiCheckBox.checked = 0 self.skipScalingMultiCheckBox.setToolTip( "If checked, PointCloudRegistration will skip scaling during the alignment." ) alignMultiWidgetLayout.addRow("Skip scaling", self.skipScalingMultiCheckBox) [ self.pointDensityMulti, self.normalSearchRadiusMulti, self.FPFHSearchRadiusMulti, self.distanceThresholdMulti, self.maxRANSACMulti, self.maxRANSACValidationMulti, self.ICPDistanceThresholdMulti ] = self.addAdvancedMenu(alignMultiWidgetLayout) # # Run landmarking Button # self.applyLandmarkMultiButton = qt.QPushButton( "Run PointCloud Registration") self.applyLandmarkMultiButton.toolTip = "Align the source meshes and landmarks with a reference mesh" self.applyLandmarkMultiButton.enabled = False alignMultiWidgetLayout.addRow(self.applyLandmarkMultiButton) # connections self.sourceModelMultiSelector.connect('validInputChanged(bool)', self.onSelectMultiProcess) self.sourceFiducialMultiSelector.connect('validInputChanged(bool)', self.onSelectMultiProcess) self.targetModelMultiSelector.connect('validInputChanged(bool)', self.onSelectMultiProcess) self.landmarkOutputSelector.connect('validInputChanged(bool)', self.onSelectMultiProcess) self.skipScalingMultiCheckBox.connect('validInputChanged(bool)', self.onSelectMultiProcess) self.applyLandmarkMultiButton.connect('clicked(bool)', self.onApplyLandmarkMulti) # Add vertical spacer self.layout.addStretch(1) # Advanced tab connections self.pointDensityMulti.connect('valueChanged(double)', self.updateParameterDictionary) self.normalSearchRadiusMulti.connect('valueChanged(double)', self.updateParameterDictionary) self.FPFHSearchRadiusMulti.connect('valueChanged(double)', self.updateParameterDictionary) self.distanceThresholdMulti.connect('valueChanged(double)', self.updateParameterDictionary) self.maxRANSACMulti.connect('valueChanged(double)', self.updateParameterDictionary) self.maxRANSACValidationMulti.connect('valueChanged(double)', self.updateParameterDictionary) self.ICPDistanceThresholdMulti.connect('valueChanged(double)', self.updateParameterDictionary) # initialize the parameter dictionary from single run parameters self.parameterDictionary = { "pointDensity": self.pointDensity.value, "normalSearchRadius": self.normalSearchRadius.value, "FPFHSearchRadius": self.FPFHSearchRadius.value, "distanceThreshold": self.distanceThreshold.value, "maxRANSAC": int(self.maxRANSAC.value), "maxRANSACValidation": int(self.maxRANSACValidation.value), "ICPDistanceThreshold": self.ICPDistanceThreshold.value } # initialize the parameter dictionary from multi run parameters self.parameterDictionaryMulti = { "pointDensity": self.pointDensityMulti.value, "normalSearchRadius": self.normalSearchRadiusMulti.value, "FPFHSearchRadius": self.FPFHSearchRadiusMulti.value, "distanceThreshold": self.distanceThresholdMulti.value, "maxRANSAC": int(self.maxRANSACMulti.value), "maxRANSACValidation": int(self.maxRANSACValidationMulti.value), "ICPDistanceThreshold": self.ICPDistanceThresholdMulti.value }
def setup(self): ScriptedLoadableModuleWidget.setup(self) self.logic = MyModuleLogic() # ------ 1. CREATE LAYOUT AND BUTTONS ------ # Layout setup: 3D Only self.layoutManager = slicer.app.layoutManager() self.layoutManager.setLayout( slicer.vtkMRMLLayoutNode.SlicerLayoutOneUp3DView) # # LOAD DATA # # Create layout collapsibleButtonLoad = ctk.ctkCollapsibleButton() collapsibleButtonLoad.text = "LOAD DATA" # title for layout self.layout.addWidget(collapsibleButtonLoad) formLayout_load = qt.QFormLayout(collapsibleButtonLoad) # Segment 1 Selector self.segment1_pathSelector = ctk.ctkPathLineEdit() self.segment1_pathSelector.enabled = True self.segment1_pathSelector.setMaximumWidth(400) self.segment1_pathSelector.currentPath = slicer.modules.mymodule.path.replace( "MyModule.py", "") + 'Data/Liver1.stl' formLayout_load.addRow("Segment 1: ", self.segment1_pathSelector) # Segment 1 Selector self.segment2_pathSelector = ctk.ctkPathLineEdit() self.segment2_pathSelector.enabled = True self.segment2_pathSelector.setMaximumWidth(400) self.segment2_pathSelector.currentPath = slicer.modules.mymodule.path.replace( "MyModule.py", "") + 'Data/Liver1beforeMM.stl' formLayout_load.addRow("Segment 2: ", self.segment2_pathSelector) # Button to load segments self.loadSegmentsButton = qt.QPushButton( "LOAD MODELS AS SEGMENTS") # text in button self.loadSegmentsButton.toolTip = "Load segments as segments" # hint text for button (appears when cursor is above the button for more than one second) self.loadSegmentsButton.enabled = True # if True it can be clicked formLayout_load.addRow( self.loadSegmentsButton) # include button in layout # # ALIGNMENT # # Create Layout collapsibleButtonAlignment = ctk.ctkCollapsibleButton() collapsibleButtonAlignment.text = "ALIGNMENT" self.layout.addWidget(collapsibleButtonAlignment) formLayout_alignment = qt.QFormLayout(collapsibleButtonAlignment) # Button for masks alignment self.alignSegmentsButton = qt.QPushButton( "ALIGN MODELS") # text in button self.alignSegmentsButton.toolTip = "Align segments" # hint text for button (appears when cursor is above the button for more than one second) self.alignSegmentsButton.enabled = True formLayout_alignment.addRow(self.alignSegmentsButton) # COMPARISON BETWEEN MASKS # # SORENSEN-DICE COEFFICIENT & HOUSDORFF DISTANCE BUTTONS # # Create layout collapsibleButtonComparison = ctk.ctkCollapsibleButton() collapsibleButtonComparison.text = "COMPARISON" # title for layout self.layout.addWidget(collapsibleButtonComparison) formLayout_comparison = qt.QFormLayout(collapsibleButtonComparison) # Button to obtain the Sorensen-Dice Coefficient self.diceCoeffButton = qt.QPushButton( "SORENSEN-DICE COEFFICIENT") # text in button self.diceCoeffButton.toolTip = "Sorensen-Dice Coefficient" # hint text for button (appears when the cursor is above the button for more than one second) self.diceCoeffButton.enabled = True # if true it can be clicked formLayout_comparison.addRow( self.diceCoeffButton) # include button in layout #Button to obtain the Hausdorff Distance self.hausDistButton = qt.QPushButton( "HAUSDORFF DISTANCE") # text in button self.hausDistButton.toolTip = qt.QPushButton( "Hausdorff Distance" ) # hint text for button (appears when the cursor is above the button for more than a second) self.hausDistButton.enabled = True # if true it can be clicked formLayout_comparison.addRow( self.hausDistButton) # include button in layout # # VISUALIZATION # # Create layout collapsibleButtonVisualization = ctk.ctkCollapsibleButton() collapsibleButtonVisualization.text = "VISUALIZATION" # title for layout self.layout.addWidget(collapsibleButtonVisualization) formLayout_visualization = qt.QFormLayout( collapsibleButtonVisualization) # # Segment visibility layout # # Create collapsible button inside layout segmentVisibility_GroupBox = ctk.ctkCollapsibleGroupBox() segmentVisibility_GroupBox.setTitle( "MODEL VISIBILITY") # title for collapsible button segmentVisibility_GroupBox.collapsed = False # if True it appears collapsed formLayout_visualization.addRow( segmentVisibility_GroupBox) # add collapsible button to layout # Create layout inside collapsible button segmentVisibility_GroupBox_Layout = qt.QFormLayout( segmentVisibility_GroupBox) # Create horizontal section segmentVisibilityLayout_1 = qt.QHBoxLayout() segmentVisibility_GroupBox_Layout.addRow( segmentVisibilityLayout_1) # insert section in current layout # Show or Hide Segment 1 in 3D scene self.segment1_checkBox = qt.QCheckBox('Segment 1') # text in checkbox self.segment1_checkBox.checked = True # if True it is initially checked self.segment1_checkBox.enabled = True # if True it can be checked segmentVisibilityLayout_1.addWidget( self.segment1_checkBox) # add checkbox to layout # Show or Hide Segment 2 in 3D scene self.segment2_checkBox = qt.QCheckBox('Segment 2') # text in checkbox self.segment2_checkBox.checked = True # if True it is initially checked self.segment2_checkBox.checked = True # if True it can be checked segmentVisibilityLayout_1.addWidget( self.segment2_checkBox) # add checkbox to layout # # Segment transparency layout # # Create collapsible button inside layout segmentOpacity_GroupBox = ctk.ctkCollapsibleGroupBox() segmentOpacity_GroupBox.setTitle( "MODEL OPACITY") # title for collapsible button segmentOpacity_GroupBox.collapsed = False # if True it appears collapsed formLayout_visualization.addRow( segmentOpacity_GroupBox) # add collapsible button to layout # Create layout inside collapsible button segmentOpacity_GroupBox_Layout = qt.QFormLayout( segmentOpacity_GroupBox) # Create an opacity Value Slider - Segment 1 self.opacityValueSliderWidget_1 = ctk.ctkSliderWidget() self.opacityValueSliderWidget_1.singleStep = 5 # step for range of values to be selected self.opacityValueSliderWidget_1.minimum = 0 # minimum value self.opacityValueSliderWidget_1.maximum = 100 # maximum value self.opacityValueSliderWidget_1.value = 100 # initial value segmentOpacity_GroupBox_Layout.addRow( "[%]: ", self.opacityValueSliderWidget_1) # add slider to layout # Create an opacity Value Slider - Segment 2 self.opacityValueSliderWidget_2 = ctk.ctkSliderWidget() self.opacityValueSliderWidget_2.singleStep = 5 # step for range of values to be selected self.opacityValueSliderWidget_2.minimum = 0 # minimum value self.opacityValueSliderWidget_2.maximum = 100 # maximum value self.opacityValueSliderWidget_2.value = 100 # initial value segmentOpacity_GroupBox_Layout.addRow( "[%]: ", self.opacityValueSliderWidget_2) # add slider to layout # # COLOR MAP # collapsibleButtonColorMap = ctk.ctkCollapsibleButton() collapsibleButtonColorMap.text = "COLOR MAP" self.layout.addWidget(collapsibleButtonColorMap) formLayout_colorMap = qt.QFormLayout(collapsibleButtonColorMap) self.showColorMapButton = qt.QPushButton( "SHOW COLOR MAP") # text in button self.showColorMapButton.toolTip = "Align segments" # hint text for button (appears when cursor is above the button for more than one second) self.showColorMapButton.enabled = True formLayout_colorMap.addRow(self.showColorMapButton) # Displayed Range group box self.displayedRange_GroupBox = ctk.ctkCollapsibleGroupBox() self.displayedRange_GroupBox.setTitle("Displayed Range") self.displayedRange_GroupBox.collapsed = False self.displayedRange_GroupBox.enabled = False formLayout_colorMap.addRow(self.displayedRange_GroupBox) displayedRange_GroupBox_Layout = qt.QFormLayout( self.displayedRange_GroupBox) displayedRange_H_Layout = qt.QHBoxLayout() displayedRange_GroupBox_Layout.addRow(displayedRange_H_Layout) ## Minimum value - displayed range self.minDisplayedRange_SpinBox = qt.QDoubleSpinBox() self.minDisplayedRange_SpinBox.setMaximum(40.0) self.minDisplayedRange_SpinBox.setMinimum(-40.0) self.minDisplayedRange_SpinBox.setSingleStep(0.1) self.minDisplayedRange_SpinBox.enabled = True self.minDisplayedRange_SpinBox.value = 0.0 displayedRange_H_Layout.addWidget(self.minDisplayedRange_SpinBox) ## Displayed range Slider self.displayedRange_SliderWidget = ctk.ctkDoubleRangeSlider() self.displayedRange_SliderWidget.setValues(0.0, 10.0) self.displayedRange_SliderWidget.orientation = 1 self.displayedRange_SliderWidget.singleStep = 0.1 self.displayedRange_SliderWidget.minimum = -40.0 self.displayedRange_SliderWidget.maximum = 40.0 displayedRange_H_Layout.addWidget(self.displayedRange_SliderWidget) ## Maximum value - displayed range self.maxDisplayedRange_SpinBox = qt.QDoubleSpinBox() self.maxDisplayedRange_SpinBox.setMaximum(40.0) self.maxDisplayedRange_SpinBox.setMinimum(-40.0) self.maxDisplayedRange_SpinBox.setSingleStep(0.1) self.maxDisplayedRange_SpinBox.enabled = True self.maxDisplayedRange_SpinBox.value = 10.0 displayedRange_H_Layout.addWidget(self.maxDisplayedRange_SpinBox) # Scalar Bar Visibility Checkbox self.ScalarBar_visibility_checkBox = qt.QCheckBox('Scalar Bar Visible') self.ScalarBar_visibility_checkBox.checked = True displayedRange_GroupBox_Layout.addRow( self.ScalarBar_visibility_checkBox) # Add vertical spacing self.layout.addStretch(1) # ------ 2. CONNECT BUTTONS WITH FUNCTIONS ------ # Connect each button with a function self.loadSegmentsButton.connect( 'clicked(bool)', self.onloadSegmentsButton ) # when the button is pressed we call the function onLoadSegment1Button self.segment1_checkBox.connect('stateChanged(int)', self.onupdateSegment1Visibility) self.segment2_checkBox.connect('stateChanged(int)', self.onupdateSegment2Visibility) self.opacityValueSliderWidget_1.connect("valueChanged(double)", self.onupdateSegment1Opacity) self.opacityValueSliderWidget_2.connect("valueChanged(double)", self.onupdateSegment2Opacity) self.alignSegmentsButton.connect('clicked(bool)', self.onAlignSegmentsButton) self.diceCoeffButton.connect('clicked(bool)', self.onDiceCoeffButton) self.hausDistButton.connect('clicked(bool)', self.onHausdorffDistButton) self.showColorMapButton.connect('clicked(bool)', self.onShowColorMapButton) self.displayedRange_SliderWidget.connect( "valuesChanged(double,double)", self.onDisplayedRangeSliderChanged) self.minDisplayedRange_SpinBox.connect( "valueChanged(double)", self.onDisplayedRangeSpinBoxChanged) self.maxDisplayedRange_SpinBox.connect( "valueChanged(double)", self.onDisplayedRangeSpinBoxChanged) self.ScalarBar_visibility_checkBox.connect( 'stateChanged(int)', self.onScalarBarVisibilityChecked)
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 setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # Set up tabs to split workflow tabsWidget = qt.QTabWidget() curvesTab = qt.QWidget() curvesTabLayout = qt.QFormLayout(curvesTab) fiducialsTab = qt.QWidget() fiducialsTabLayout = qt.QFormLayout(fiducialsTab) batchTab = qt.QWidget() batchTabLayout = qt.QFormLayout(batchTab) tabsWidget.addTab(curvesTab, "Merge Curves") tabsWidget.addTab(fiducialsTab, "Merge Landmark Sets") tabsWidget.addTab(batchTab, "Batch Merge Landmark Sets") self.layout.addWidget(tabsWidget) ################## Curves Tab # # Parameters Area # parametersCurveCollapsibleButton = ctk.ctkCollapsibleButton() parametersCurveCollapsibleButton.text = "Curve Viewer" curvesTabLayout.addRow(parametersCurveCollapsibleButton) # Layout within the dummy collapsible button parametersCurveFormLayout = qt.QFormLayout( parametersCurveCollapsibleButton) # # check box to trigger taking screen shots for later use in tutorials # self.continuousCurvesCheckBox = qt.QCheckBox() self.continuousCurvesCheckBox.checked = 0 self.continuousCurvesCheckBox.setToolTip( "If checked, redundant points will be removed on merging.") parametersCurveFormLayout.addRow("Contiuous curves", self.continuousCurvesCheckBox) # # markups view # self.markupsView = slicer.qMRMLSubjectHierarchyTreeView() self.markupsView.setMRMLScene(slicer.mrmlScene) self.markupsView.setMultiSelection(True) self.markupsView.setAlternatingRowColors(True) self.markupsView.setDragDropMode(qt.QAbstractItemView().DragDrop) self.markupsView.setColumnHidden( self.markupsView.model().transformColumn, True) self.markupsView.sortFilterProxyModel().setNodeTypes( ["vtkMRMLMarkupsCurveNode"]) parametersCurveFormLayout.addRow(self.markupsView) # # Merge Button # self.mergeButton = qt.QPushButton("Merge highlighted nodes") self.mergeButton.toolTip = "Generate a single merged markup file from the selected nodes" self.mergeButton.enabled = False parametersCurveFormLayout.addRow(self.mergeButton) # connections self.mergeButton.connect('clicked(bool)', self.onMergeButton) self.markupsView.connect('currentItemChanged(vtkIdType)', self.updateMergeButton) ################ Landmark Set Tab # # Parameters Area # parametersLMCollapsibleButton = ctk.ctkCollapsibleButton() parametersLMCollapsibleButton.text = "Landmark Viewer" fiducialsTabLayout.addRow(parametersLMCollapsibleButton) # Layout within the dummy collapsible button parametersLMFormLayout = qt.QGridLayout(parametersLMCollapsibleButton) # # markups view # self.markupsFiducialView = slicer.qMRMLSubjectHierarchyTreeView() self.markupsFiducialView.setMRMLScene(slicer.mrmlScene) self.markupsFiducialView.setMultiSelection(True) self.markupsFiducialView.setAlternatingRowColors(True) self.markupsFiducialView.setDragDropMode( qt.QAbstractItemView().DragDrop) self.markupsFiducialView.setColumnHidden( self.markupsView.model().transformColumn, True) self.markupsFiducialView.sortFilterProxyModel().setNodeTypes( ["vtkMRMLMarkupsFiducialNode"]) parametersLMFormLayout.addWidget(self.markupsFiducialView, 0, 0, 1, 3) # # Set landmark type menu # boxLabel = qt.QLabel("Select landmark type description to apply: ") self.LandmarkTypeSelection = qt.QComboBox() self.LandmarkTypeSelection.addItems( ["Select", "Fixed", "Semi", "No description"]) parametersLMFormLayout.addWidget(boxLabel, 1, 0) parametersLMFormLayout.addWidget(self.LandmarkTypeSelection, 1, 1) # # Apply Landmark Type Button # self.ApplyLMButton = qt.QPushButton("Apply to highlighted nodes") self.ApplyLMButton.toolTip = "Apply the selected landmark type to points in the the selected nodes" self.ApplyLMButton.enabled = False parametersLMFormLayout.addWidget(self.ApplyLMButton, 1, 2) # # Merge Button # self.mergeLMButton = qt.QPushButton("Merge highlighted nodes") self.mergeLMButton.toolTip = "Generate a single merged markup file from the selected nodes" self.mergeLMButton.enabled = False parametersLMFormLayout.addWidget(self.mergeLMButton, 2, 0, 1, 3) # connections self.mergeLMButton.connect('clicked(bool)', self.onMergeLMButton) self.ApplyLMButton.connect('clicked(bool)', self.onApplyLMButton) self.markupsFiducialView.connect('currentItemChanged(vtkIdType)', self.updateMergeLMButton) self.LandmarkTypeSelection.connect('currentIndexChanged(int)', self.updateApplyLMButton) ################ Batch Run LM Merge Tab # # Fixed LM Area # fixedBatchCollapsibleButton = ctk.ctkCollapsibleButton() fixedBatchCollapsibleButton.text = "Fixed LM File Selection" batchTabLayout.addRow(fixedBatchCollapsibleButton) # Layout within the dummy collapsible button fixedBatchLayout = qt.QFormLayout(fixedBatchCollapsibleButton) # # Browse Fixed LM Button # self.browseFixedLMButton = qt.QPushButton("Select files...") self.browseFixedLMButton.toolTip = "Select one fixed landmark file for each subject" self.browseFixedLMButton.enabled = True fixedBatchLayout.addRow(self.browseFixedLMButton) # # File viewer box # self.fixedFileTable = qt.QTextEdit() fixedBatchLayout.addRow(self.fixedFileTable) # # Semi LM Area # semiBatchCollapsibleButton = ctk.ctkCollapsibleButton() semiBatchCollapsibleButton.text = "Semi LM File Selection" batchTabLayout.addRow(semiBatchCollapsibleButton) # Layout within the dummy collapsible button semiBatchLayout = qt.QFormLayout(semiBatchCollapsibleButton) # # Browse Fixed LM Button # self.browseSemiLMButton = qt.QPushButton("Select files...") self.browseSemiLMButton.toolTip = "Select one semi-landmark file for each subject, in the same order as the fixed landmarks" self.browseSemiLMButton.enabled = True semiBatchLayout.addRow(self.browseSemiLMButton) # # File viewer box # self.semiFileTable = qt.QTextEdit() semiBatchLayout.addRow(self.semiFileTable) # # Merge LM Area # batchMergeCollapsibleButton = ctk.ctkCollapsibleButton() batchMergeCollapsibleButton.text = "Run merge" batchTabLayout.addRow(batchMergeCollapsibleButton) # Layout within the dummy collapsible button batchMergeLayout = qt.QFormLayout(batchMergeCollapsibleButton) # # Select output landmark directory # self.outputDirectorySelector = ctk.ctkPathLineEdit() self.outputDirectorySelector.filters = ctk.ctkPathLineEdit.Dirs self.outputDirectorySelector.toolTip = "Select the output directory where the merged landmark nodes will be saved" batchMergeLayout.addRow("Select output landmark directory: ", self.outputDirectorySelector) # # Batch Merge Button # self.batchMergeButton = qt.QPushButton( "Merge fixed and semi-landmark nodes") self.batchMergeButton.toolTip = "Generate a single merged markup file from the selected nodes" self.batchMergeButton.enabled = False batchMergeLayout.addRow(self.batchMergeButton) # # Clear Button # self.clearButton = qt.QPushButton("Clear landmark file selections") self.clearButton.toolTip = "Clear the landmark files selected in the viewer boxes" self.clearButton.enabled = False batchMergeLayout.addRow(self.clearButton) # connections self.browseFixedLMButton.connect('clicked(bool)', self.addFixedByBrowsing) self.browseSemiLMButton.connect('clicked(bool)', self.addSemiByBrowsing) self.outputDirectorySelector.connect('validInputChanged(bool)', self.onSelectDirectory) self.batchMergeButton.connect('clicked(bool)', self.onBatchMergeButton) self.clearButton.connect('clicked(bool)', self.onClearButton) # Add vertical spacer self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Launch PureData pureDataCollapsibleButton = ctk.ctkCollapsibleButton() pureDataCollapsibleButton.text = "PureData server" self.layout.addWidget(pureDataCollapsibleButton) pureDataFormLayout = qt.QFormLayout(pureDataCollapsibleButton) self.pureDataConfigFilePathSelector = ctk.ctkPathLineEdit() self.pureDataConfigFilePathSelector.settingKey = "OpenSoundControl/PureDataConfigurationFilePath" self.pureDataConfigFilePathSelector.setSizePolicy( qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred) self.pureDataConfigFilePathSelector.setToolTip( "Set PureData configuration file that will be loaded when the server is launched." ) pureDataFormLayout.addRow("PureData configuration:", self.pureDataConfigFilePathSelector) self.buttonStartServer = qt.QPushButton("Start server") self.buttonStartServer.toolTip = "Start PureData server that will receive OSC messages" self.buttonStartServer.connect('clicked()', self.startServer) self.buttonStopServer = qt.QPushButton("Stop server") self.buttonStopServer.toolTip = "Stop PureData server" self.buttonStopServer.connect('clicked()', self.stopServer) hbox = qt.QHBoxLayout() hbox.addWidget(self.buttonStartServer) hbox.addWidget(self.buttonStopServer) pureDataFormLayout.addRow(hbox) # Connection connectionCollapsibleButton = ctk.ctkCollapsibleButton() connectionCollapsibleButton.text = "Connection" self.layout.addWidget(connectionCollapsibleButton) connectionFormLayout = qt.QFormLayout(connectionCollapsibleButton) self.hostnameLineEdit = qt.QLineEdit("localhost") connectionFormLayout.addRow("Host name: ", self.hostnameLineEdit) self.portLineEdit = qt.QLineEdit("7400") self.portLineEdit.setValidator( qt.QIntValidator(0, 65535, self.portLineEdit)) connectionFormLayout.addRow("Port: ", self.portLineEdit) self.buttonConnect = qt.QPushButton("Connect") self.buttonConnect.toolTip = "Connect to OSC module" connectionFormLayout.addWidget(self.buttonConnect) self.buttonConnect.connect('clicked()', self.connect) # Send message messageCollapsibleButton = ctk.ctkCollapsibleButton() messageCollapsibleButton.text = "Messaging" self.layout.addWidget(messageCollapsibleButton) messageFormLayout = qt.QFormLayout(messageCollapsibleButton) self.addressLineEdit = qt.QLineEdit() self.addressLineEdit.setText("/SoundNav/1") messageFormLayout.addRow("Address:", self.addressLineEdit) self.valueLineEdit = qt.QLineEdit() self.valueLineEdit.setText("") messageFormLayout.addRow("Value:", self.valueLineEdit) self.buttonSend = qt.QPushButton("Send") self.buttonSend.toolTip = "Send OSC message" messageFormLayout.addWidget(self.buttonSend) self.buttonSend.connect('clicked(bool)', self.sendMessage) # # Advanced area # self.advancedCollapsibleButton = ctk.ctkCollapsibleButton() self.advancedCollapsibleButton.text = "Advanced" self.advancedCollapsibleButton.collapsed = True self.layout.addWidget(self.advancedCollapsibleButton) advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton) self.logDetailsCheckBox = qt.QCheckBox(" ") self.logDetailsCheckBox.checked = False self.logDetailsCheckBox.setToolTip( "Add details about all sent messages to the application log. It may slow down the execution." ) advancedFormLayout.addRow("Log messages:", self.logDetailsCheckBox) self.logDetailsCheckBox.connect("toggled(bool)", self.logic.setLoggingEnabled) pureDataExecutablePath = self.logic.getPureDataExecutablePath() self.pureDataExecutablePathSelector = ctk.ctkPathLineEdit() self.pureDataExecutablePathSelector.filters = ctk.ctkPathLineEdit.Executable + ctk.ctkPathLineEdit.Files from sys import platform self.pureDataExecutablePathSelector.nameFilters = [ "PureData (pd.exe)" if platform == "win32" else "PureData (pd*)" ] self.pureDataExecutablePathSelector.setCurrentPath( pureDataExecutablePath) self.pureDataExecutablePathSelector.setSizePolicy( qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred) self.pureDataExecutablePathSelector.setToolTip( "Set PureData executable (pd) path.") advancedFormLayout.addRow("PureData executable:", self.pureDataExecutablePathSelector) self.pureDataExecutablePathSelector.connect( 'currentPathChanged(QString)', self.logic.setPureDataExecutablePath) self.showPureDataGUI = qt.QCheckBox(" ") self.showPureDataGUI.checked = False self.showPureDataGUI.setToolTip( "Start PureData server with graphical user interface visible. Useful for development and troubleshooting." ) advancedFormLayout.addRow("Start PureData with GUI:", self.showPureDataGUI) # Add vertical spacer self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) self.inputDirectory = ctk.ctkPathLineEdit() self.inputDirectory.filters = ctk.ctkPathLineEdit.Dirs self.inputDirectory.setToolTip("Select directory containing volumes") parametersFormLayout.addRow("Input directory: ", self.inputDirectory) # Select output directory self.outputDirectory = ctk.ctkPathLineEdit() self.outputDirectory.filters = ctk.ctkPathLineEdit.Dirs self.outputDirectory.setToolTip("Select directory for output models: ") parametersFormLayout.addRow("Output directory: ", self.outputDirectory) # # Select the extension type # self.extensionOptionGZ = qt.QRadioButton(".nii.gz") self.extensionOptionGZ.setChecked(True) parametersFormLayout.addRow("Select extension type: ", self.extensionOptionGZ) # # set threshold value # self.threshold = ctk.ctkDoubleSpinBox() self.threshold.singleStep = 1 self.threshold.minimum = 0 self.threshold.maximum = 100000 self.threshold.setDecimals(0) self.threshold.value = 500 self.threshold.setToolTip( "Select threshold for segmentation of volume") parametersFormLayout.addRow("Threshold for segmentation:", self.threshold) # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Generate VolumeToMeshs." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # # 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) # connections self.inputDirectory.connect('validInputChanged(bool)', self.onSelectInput) self.outputDirectory.connect('validInputChanged(bool)', self.onSelectOutput) self.applyButton.connect('clicked(bool)', self.onApplyButton) # Add vertical spacer self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) self.logic = ElastixLogic() self.logic.logCallback = self.addLog self.registrationInProgress = False # Instantiate and connect widgets ... # Parameter sets defaultinputParametersCollapsibleButton = ctk.ctkCollapsibleButton() defaultinputParametersCollapsibleButton.text = "Parameter set" defaultinputParametersCollapsibleButton.collapsed = True self.layout.addWidget(defaultinputParametersCollapsibleButton) defaultParametersLayout = qt.QFormLayout(defaultinputParametersCollapsibleButton) self.parameterNodeSelector = slicer.qMRMLNodeComboBox() self.parameterNodeSelector.nodeTypes = ["vtkMRMLScriptedModuleNode"] self.parameterNodeSelector.addAttribute( "vtkMRMLScriptedModuleNode", "ModuleName", "Elastix" ) self.parameterNodeSelector.selectNodeUponCreation = True self.parameterNodeSelector.addEnabled = True self.parameterNodeSelector.renameEnabled = True self.parameterNodeSelector.removeEnabled = True self.parameterNodeSelector.noneEnabled = False self.parameterNodeSelector.showHidden = True self.parameterNodeSelector.showChildNodeTypes = False self.parameterNodeSelector.baseName = "General Registration (Elastix)" self.parameterNodeSelector.setMRMLScene( slicer.mrmlScene ) self.parameterNodeSelector.setToolTip( "Pick parameter set" ) defaultParametersLayout.addRow("Parameter set: ", self.parameterNodeSelector) # # Inputs # inputParametersCollapsibleButton = ctk.ctkCollapsibleButton() inputParametersCollapsibleButton.text = "Inputs" self.layout.addWidget(inputParametersCollapsibleButton) # Layout within the dummy collapsible button inputParametersFormLayout = qt.QFormLayout(inputParametersCollapsibleButton) # # fixed volume selector # self.fixedVolumeSelector = slicer.qMRMLNodeComboBox() self.fixedVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] self.fixedVolumeSelector.selectNodeUponCreation = True self.fixedVolumeSelector.addEnabled = False self.fixedVolumeSelector.removeEnabled = False self.fixedVolumeSelector.noneEnabled = False self.fixedVolumeSelector.showHidden = False self.fixedVolumeSelector.showChildNodeTypes = False self.fixedVolumeSelector.setMRMLScene( slicer.mrmlScene ) self.fixedVolumeSelector.setToolTip( "The moving volume will be transformed into this image space." ) inputParametersFormLayout.addRow("Fixed volume: ", self.fixedVolumeSelector) # # moving volume selector # self.movingVolumeSelector = slicer.qMRMLNodeComboBox() self.movingVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] self.movingVolumeSelector.selectNodeUponCreation = True self.movingVolumeSelector.addEnabled = False self.movingVolumeSelector.removeEnabled = False self.movingVolumeSelector.noneEnabled = False self.movingVolumeSelector.showHidden = False self.movingVolumeSelector.showChildNodeTypes = False self.movingVolumeSelector.setMRMLScene( slicer.mrmlScene ) self.movingVolumeSelector.setToolTip( "This volume will be transformed into the fixed image space" ) inputParametersFormLayout.addRow("Moving volume: ", self.movingVolumeSelector) self.registrationPresetSelector = qt.QComboBox() for preset in self.logic.getRegistrationPresets(): self.registrationPresetSelector.addItem("{0} ({1})".format(preset[RegistrationPresets_Modality], preset[RegistrationPresets_Content])) inputParametersFormLayout.addRow("Preset: ", self.registrationPresetSelector) # # Outputs # maskingParametersCollapsibleButton = ctk.ctkCollapsibleButton() maskingParametersCollapsibleButton.text = "Masking" maskingParametersCollapsibleButton.collapsed = True self.layout.addWidget(maskingParametersCollapsibleButton) # Layout within the dummy collapsible button maskingParametersFormLayout = qt.QFormLayout(maskingParametersCollapsibleButton) # # fixed volume mask selector # self.fixedVolumeMaskSelector = slicer.qMRMLNodeComboBox() self.fixedVolumeMaskSelector.nodeTypes = ["vtkMRMLLabelMapVolumeNode"] self.fixedVolumeMaskSelector.addEnabled = False self.fixedVolumeMaskSelector.removeEnabled = False self.fixedVolumeMaskSelector.noneEnabled = True self.fixedVolumeMaskSelector.showHidden = False self.fixedVolumeMaskSelector.showChildNodeTypes = False self.fixedVolumeMaskSelector.setMRMLScene( slicer.mrmlScene ) self.fixedVolumeMaskSelector.setToolTip("Areas of the fixed volume where mask label is 0 will be ignored in the registration.") maskingParametersFormLayout.addRow("Fixed volume mask: ", self.fixedVolumeMaskSelector) # # moving volume mask selector # self.movingVolumeMaskSelector = slicer.qMRMLNodeComboBox() self.movingVolumeMaskSelector.nodeTypes = ["vtkMRMLLabelMapVolumeNode"] self.movingVolumeMaskSelector.selectNodeUponCreation = True self.movingVolumeMaskSelector.addEnabled = False self.movingVolumeMaskSelector.removeEnabled = False self.movingVolumeMaskSelector.noneEnabled = True self.movingVolumeMaskSelector.showHidden = False self.movingVolumeMaskSelector.showChildNodeTypes = False self.movingVolumeMaskSelector.setMRMLScene( slicer.mrmlScene ) self.movingVolumeMaskSelector.setToolTip("Areas of the moving volume where mask label is 0 will be ignored in the registration") maskingParametersFormLayout.addRow("Moving volume mask: ", self.movingVolumeMaskSelector) # # Outputs # outputParametersCollapsibleButton = ctk.ctkCollapsibleButton() outputParametersCollapsibleButton.text = "Outputs" self.layout.addWidget(outputParametersCollapsibleButton) # Layout within the dummy collapsible button outputParametersFormLayout = qt.QFormLayout(outputParametersCollapsibleButton) # # output volume selector # self.outputVolumeSelector = slicer.qMRMLNodeComboBox() self.outputVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] self.outputVolumeSelector.selectNodeUponCreation = True self.outputVolumeSelector.addEnabled = True self.outputVolumeSelector.renameEnabled = True self.outputVolumeSelector.removeEnabled = True self.outputVolumeSelector.noneEnabled = True self.outputVolumeSelector.showHidden = False self.outputVolumeSelector.showChildNodeTypes = False self.outputVolumeSelector.setMRMLScene( slicer.mrmlScene ) self.outputVolumeSelector.setToolTip( "(optional) The moving image warped to the fixed image space. NOTE: You must set at least one output object (transform and/or output volume)" ) outputParametersFormLayout.addRow("Output volume: ", self.outputVolumeSelector) # # output transform selector # self.outputTransformSelector = slicer.qMRMLNodeComboBox() self.outputTransformSelector.nodeTypes = ["vtkMRMLTransformNode"] self.outputTransformSelector.selectNodeUponCreation = True self.outputTransformSelector.addEnabled = True self.outputTransformSelector.renameEnabled = True self.outputTransformSelector.removeEnabled = True self.outputTransformSelector.noneEnabled = True self.outputTransformSelector.showHidden = False self.outputTransformSelector.showChildNodeTypes = False self.outputTransformSelector.setMRMLScene( slicer.mrmlScene ) self.outputTransformSelector.setToolTip( "(optional) Computed displacement field that transform nodes from moving volume space to fixed volume space. NOTE: You must set at least one output object (transform and/or output volume)." ) outputParametersFormLayout.addRow("Output transform: ", self.outputTransformSelector) # # Advanced area # self.advancedCollapsibleButton = ctk.ctkCollapsibleButton() self.advancedCollapsibleButton.text = "Advanced" self.advancedCollapsibleButton.collapsed = True self.layout.addWidget(self.advancedCollapsibleButton) advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton) self.showDetailedLogDuringExecutionCheckBox = qt.QCheckBox(" ") self.showDetailedLogDuringExecutionCheckBox.checked = False self.showDetailedLogDuringExecutionCheckBox.setToolTip("Show detailed log during registration.") advancedFormLayout.addRow("Show detailed log during registration:", self.showDetailedLogDuringExecutionCheckBox) self.keepTemporaryFilesCheckBox = qt.QCheckBox(" ") self.keepTemporaryFilesCheckBox.checked = False self.keepTemporaryFilesCheckBox.setToolTip("Keep temporary files (inputs, computed outputs, logs) after the registration is completed.") self.showTemporaryFilesFolderButton = qt.QPushButton("Show temp folder") self.showTemporaryFilesFolderButton.toolTip = "Open the folder where temporary files are stored." self.showTemporaryFilesFolderButton.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred) hbox = qt.QHBoxLayout() hbox.addWidget(self.keepTemporaryFilesCheckBox) hbox.addWidget(self.showTemporaryFilesFolderButton) advancedFormLayout.addRow("Keep temporary files:", hbox) self.showRegistrationParametersDatabaseFolderButton = qt.QPushButton("Show database folder") self.showRegistrationParametersDatabaseFolderButton.toolTip = "Open the folder where temporary files are stored." self.showRegistrationParametersDatabaseFolderButton.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred) advancedFormLayout.addRow("Registration presets:", self.showRegistrationParametersDatabaseFolderButton) customElastixBinDir = self.logic.getCustomElastixBinDir() self.customElastixBinDirSelector = ctk.ctkPathLineEdit() self.customElastixBinDirSelector.filters = ctk.ctkPathLineEdit.Dirs self.customElastixBinDirSelector.setCurrentPath(customElastixBinDir) self.customElastixBinDirSelector.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred) self.customElastixBinDirSelector.setToolTip("Set bin directory of an Elastix installation (where elastix executable is located). " "If value is empty then default elastix (bundled with SlicerElastix extension) will be used.") advancedFormLayout.addRow("Custom Elastix toolbox location:", self.customElastixBinDirSelector) # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Run the algorithm." self.applyButton.enabled = False self.layout.addWidget(self.applyButton) self.statusLabel = qt.QPlainTextEdit() self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse) self.statusLabel.setCenterOnScroll(True) self.layout.addWidget(self.statusLabel) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.showTemporaryFilesFolderButton.connect('clicked(bool)', self.onShowTemporaryFilesFolder) self.showRegistrationParametersDatabaseFolderButton.connect('clicked(bool)', self.onShowRegistrationParametersDatabaseFolder) self.fixedVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) self.movingVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) self.outputVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) self.outputTransformSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) # Immediately update deleteTemporaryFiles in the logic to make it possible to decide to # keep the temporary file while the registration is running self.keepTemporaryFilesCheckBox.connect("toggled(bool)", self.onKeepTemporaryFilesToggled) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelect()
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 selector # # File dialog to select a file template for series self.inputFileSelector = ctk.ctkPathLineEdit() self.inputFileSelector.filters = ctk.ctkPathLineEdit().Files self.inputFileSelector.setToolTip( "Select log file from a directory of images.") parametersFormLayout.addRow("Select log file from image series:", self.inputFileSelector) # # output volume selector # # 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.renameEnabled = True # self.outputSelector.setMRMLScene( slicer.mrmlScene ) # self.outputSelector.setToolTip( "Pick the output to the algorithm." ) # parametersFormLayout.addRow("Output Volume: ", self.outputSelector) # # 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) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) #self.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) self.inputFileSelector.connect("currentPathChanged(const QString &)", self.onSelect) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelect()
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) # # Select landmark file to import # self.inputFileSelector = ctk.ctkPathLineEdit() self.inputFileSelector.setToolTip( "Select Morphologika landmark file for conversion") parametersFormLayout.addRow( "Select file containing landmark names and coordinates to load:", self.inputFileSelector) # # output directory selector # self.outputDirectory = ctk.ctkDirectoryButton() self.outputDirectory.directory = qt.QDir.homePath() parametersFormLayout.addRow("Output Directory:", self.outputDirectory) # # 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 conversion." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.inputFileSelector.connect('validInputChanged(bool)', self.onSelectInput) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelectInput()
def setup(self): ScriptedLoadableModuleWidget.setup(self) self.logic = Collect_Training_ImagesLogic() self.moduleDir = os.path.dirname(slicer.modules.collect_training_images.path) # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) #self.imageSaveDirectory = qt.QLineEdit("Select directory to save images") #parametersFormLayout.addRow(self.imageSaveDirectory) self.modelSelector = qt.QComboBox() self.modelSelector.addItems(["Select model"]) modelDirectoryContents = os.listdir(os.path.join(self.moduleDir,os.pardir,"Models")) modelNames = [dir for dir in modelDirectoryContents if dir.find(".") == -1 and dir != "Dockerfile"] self.modelSelector.addItems(["Create new model"]) self.modelSelector.addItems(modelNames) parametersFormLayout.addRow(self.modelSelector) #self.imageSaveDirectoryLabel = qt.QLabel("Training photo directory:") #parametersFormLayout.addRow(self.imageSaveDirectoryLabel) self.imageSaveDirectoryLineEdit = ctk.ctkPathLineEdit() #node = self.logic.getParameterNode() imageSaveDirectory = os.path.dirname(slicer.modules.collect_training_images.path) self.imageSaveDirectoryLineEdit.currentPath = imageSaveDirectory self.imageSaveDirectoryLineEdit.filters = ctk.ctkPathLineEdit.Dirs self.imageSaveDirectoryLineEdit.options = ctk.ctkPathLineEdit.DontUseSheet self.imageSaveDirectoryLineEdit.options = ctk.ctkPathLineEdit.ShowDirsOnly self.imageSaveDirectoryLineEdit.showHistoryButton = False self.imageSaveDirectoryLineEdit.setMinimumWidth(100) self.imageSaveDirectoryLineEdit.setMaximumWidth(500) #parametersFormLayout.addRow(self.imageSaveDirectoryLineEdit) self.imageClassComboBox = qt.QComboBox() self.imageClassComboBox.addItems(["Select image class","Create new image class"]) parametersFormLayout.addRow(self.imageClassComboBox) # # Start/Stop Image Collection Button # self.startStopCollectingImagesButton = qt.QPushButton("Start Image Collection") self.startStopCollectingImagesButton.toolTip = "Collect training images." self.startStopCollectingImagesButton.enabled = False parametersFormLayout.addRow(self.startStopCollectingImagesButton) self.infoLabel = qt.QLabel("") parametersFormLayout.addRow(self.infoLabel) # connections self.modelSelector.connect('currentIndexChanged(int)',self.onModelSelected) self.startStopCollectingImagesButton.connect('clicked(bool)', self.onStartStopCollectingImagesButton) self.imageClassComboBox.connect('currentIndexChanged(int)',self.onImageClassSelected) # Add vertical spacer self.layout.addStretch(1) # Refresh Start/Stop Collecting Images Button state self.onSelect() try: self.webcamReference = slicer.util.getNode('Webcam_Reference') except slicer.util.MRMLNodeNotFoundException: #if not self.webcamReference: imageSpacing = [0.2, 0.2, 0.2] imageData = vtk.vtkImageData() imageData.SetDimensions(640, 480, 1) imageData.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1) thresholder = vtk.vtkImageThreshold() thresholder.SetInputData(imageData) thresholder.SetInValue(0) thresholder.SetOutValue(0) # Create volume node self.webcamReference = slicer.vtkMRMLVectorVolumeNode() self.webcamReference.SetName('Webcam_Reference') self.webcamReference.SetSpacing(imageSpacing) self.webcamReference.SetImageDataConnection(thresholder.GetOutputPort()) # Add volume to scene slicer.mrmlScene.AddNode(self.webcamReference) displayNode = slicer.vtkMRMLVectorVolumeDisplayNode() slicer.mrmlScene.AddNode(displayNode) self.webcamReference.SetAndObserveDisplayNodeID(displayNode.GetID()) self.webcamConnectorNode = self.createWebcamPlusConnector() self.webcamConnectorNode.Start() self.setupWebcamResliceDriver()
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) # # Select base mesh # self.modelSelector = slicer.qMRMLNodeComboBox() self.modelSelector.nodeTypes = (("vtkMRMLModelNode"), "") self.modelSelector.selectNodeUponCreation = False self.modelSelector.addEnabled = False self.modelSelector.removeEnabled = False self.modelSelector.noneEnabled = True self.modelSelector.showHidden = False self.modelSelector.setMRMLScene(slicer.mrmlScene) parametersFormLayout.addRow("Base mesh: ", self.modelSelector) # # Select base landmark file # #self.baseLMFile=ctk.ctkPathLineEdit() #self.baseLMFile.setToolTip( "Select file specifying base landmarks" ) #parametersFormLayout.addRow("Base landmark file: ", self.baseLMFile) self.baseLMSelect = slicer.qMRMLNodeComboBox() self.baseLMSelect.nodeTypes = (('vtkMRMLMarkupsFiducialNode'), "") self.baseLMSelect.selectNodeUponCreation = False self.baseLMSelect.addEnabled = False self.baseLMSelect.removeEnabled = False self.baseLMSelect.noneEnabled = True self.baseLMSelect.showHidden = False self.baseLMSelect.showChildNodeTypes = False self.baseLMSelect.setMRMLScene(slicer.mrmlScene) parametersFormLayout.addRow("Base landmarks: ", self.baseLMSelect) # # Select base semi-landmark file # #self.baseLMFile=ctk.ctkPathLineEdit() #self.baseLMFile.setToolTip( "Select file specifying base landmarks" ) #parametersFormLayout.addRow("Base landmark file: ", self.baseLMFile) self.baseSLMSelect = slicer.qMRMLNodeComboBox() self.baseSLMSelect.nodeTypes = (('vtkMRMLMarkupsFiducialNode'), "") self.baseSLMSelect.selectNodeUponCreation = False self.baseSLMSelect.addEnabled = False self.baseSLMSelect.removeEnabled = False self.baseSLMSelect.noneEnabled = True self.baseSLMSelect.showHidden = False self.baseSLMSelect.showChildNodeTypes = False self.baseSLMSelect.setMRMLScene(slicer.mrmlScene) parametersFormLayout.addRow("Base semi-landmarks: ", self.baseSLMSelect) # # Select meshes directory # self.meshDirectory = ctk.ctkPathLineEdit() self.meshDirectory.filters = ctk.ctkPathLineEdit.Dirs self.meshDirectory.setToolTip("Select directory containing meshes") parametersFormLayout.addRow("Mesh directory: ", self.meshDirectory) # # Select landmarks directory # self.landmarkDirectory = ctk.ctkPathLineEdit() self.landmarkDirectory.filters = ctk.ctkPathLineEdit.Dirs self.landmarkDirectory.setToolTip( "Select directory containing landmarks") parametersFormLayout.addRow("Landmark directory: ", self.landmarkDirectory) # # Select semi-landmarks directory # self.semilandmarkDirectory = ctk.ctkPathLineEdit() self.semilandmarkDirectory.filters = ctk.ctkPathLineEdit.Dirs self.semilandmarkDirectory.setToolTip( "Select directory containing semi-landmarks") self.semilandmarkDirectory.enabled = False parametersFormLayout.addRow("Semi-landmark directory: ", self.semilandmarkDirectory) # # Select output directory # self.outputDirectory = ctk.ctkPathLineEdit() self.outputDirectory.filters = ctk.ctkPathLineEdit.Dirs self.outputDirectory.currentPath = slicer.app.temporaryPath self.outputDirectory.setToolTip( "Select directory to save output distance maps") parametersFormLayout.addRow("Output directory: ", self.outputDirectory) # # Select distance metric # self.unSignedDistanceOption = qt.QRadioButton() self.unSignedDistanceOption.setChecked(True) parametersFormLayout.addRow("Unsigned Distance: ", self.unSignedDistanceOption) self.signedDistanceOption = qt.QRadioButton() self.signedDistanceOption.setChecked(False) parametersFormLayout.addRow("Signed Distance: ", self.signedDistanceOption) # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Generate MeshDistanceMeasurements." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # connections self.modelSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onSelect) self.baseLMSelect.connect('currentNodeChanged(vtkMRMLNode*)', self.onSelect) self.meshDirectory.connect('validInputChanged(bool)', self.onSelect) self.baseSLMSelect.connect('currentNodeChanged(bool)', self.onSelectBaseSLM) self.semilandmarkDirectory.connect('validInputChanged(bool)', self.onSelect) self.applyButton.connect('clicked(bool)', self.onApplyButton) # Add vertical spacer self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) self.logic = SegmentMesherLogic() self.logic.logCallback = self.addLog self.modelGenerationInProgress = False # Instantiate and connect widgets ... # Parameter sets defaultinputParametersCollapsibleButton = ctk.ctkCollapsibleButton() defaultinputParametersCollapsibleButton.text = "Parameter set" defaultinputParametersCollapsibleButton.collapsed = True self.layout.addWidget(defaultinputParametersCollapsibleButton) defaultParametersLayout = qt.QFormLayout(defaultinputParametersCollapsibleButton) self.parameterNodeSelector = slicer.qMRMLNodeComboBox() self.parameterNodeSelector.nodeTypes = ["vtkMRMLScriptedModuleNode"] self.parameterNodeSelector.addAttribute( "vtkMRMLScriptedModuleNode", "ModuleName", "SegmentMesher" ) self.parameterNodeSelector.selectNodeUponCreation = True self.parameterNodeSelector.addEnabled = True self.parameterNodeSelector.renameEnabled = True self.parameterNodeSelector.removeEnabled = True self.parameterNodeSelector.noneEnabled = False self.parameterNodeSelector.showHidden = True self.parameterNodeSelector.showChildNodeTypes = False self.parameterNodeSelector.baseName = "SegmentMesher" self.parameterNodeSelector.setMRMLScene( slicer.mrmlScene ) self.parameterNodeSelector.setToolTip( "Pick parameter set" ) defaultParametersLayout.addRow("Parameter set: ", self.parameterNodeSelector) # # Inputs # inputParametersCollapsibleButton = ctk.ctkCollapsibleButton() inputParametersCollapsibleButton.text = "Inputs" self.layout.addWidget(inputParametersCollapsibleButton) # Layout within the dummy collapsible button inputParametersFormLayout = qt.QFormLayout(inputParametersCollapsibleButton) self.inputModelSelector = slicer.qMRMLNodeComboBox() self.inputModelSelector.nodeTypes = ["vtkMRMLSegmentationNode"] self.inputModelSelector.selectNodeUponCreation = True self.inputModelSelector.addEnabled = False self.inputModelSelector.removeEnabled = False self.inputModelSelector.noneEnabled = False self.inputModelSelector.showHidden = False self.inputModelSelector.showChildNodeTypes = False self.inputModelSelector.setMRMLScene( slicer.mrmlScene ) self.inputModelSelector.setToolTip( "Volumetric mesh will be generated for all visible segments in this segmentation node." ) inputParametersFormLayout.addRow("Input segmentation: ", self.inputModelSelector) self.methodSelectorComboBox = qt.QComboBox() self.methodSelectorComboBox.addItem("Cleaver", METHOD_CLEAVER) self.methodSelectorComboBox.addItem("TetGen", METHOD_TETGEN) inputParametersFormLayout.addRow("Meshing method: ", self.methodSelectorComboBox) # # Outputs # outputParametersCollapsibleButton = ctk.ctkCollapsibleButton() outputParametersCollapsibleButton.text = "Outputs" self.layout.addWidget(outputParametersCollapsibleButton) outputParametersFormLayout = qt.QFormLayout(outputParametersCollapsibleButton) # # output volume selector # self.outputModelSelector = slicer.qMRMLNodeComboBox() self.outputModelSelector.nodeTypes = ["vtkMRMLModelNode"] self.outputModelSelector.selectNodeUponCreation = True self.outputModelSelector.addEnabled = True self.outputModelSelector.renameEnabled = True self.outputModelSelector.removeEnabled = True self.outputModelSelector.noneEnabled = False self.outputModelSelector.showHidden = False self.outputModelSelector.showChildNodeTypes = False self.outputModelSelector.setMRMLScene( slicer.mrmlScene ) self.outputModelSelector.setToolTip( "Created volumetric mesh" ) outputParametersFormLayout.addRow("Output model: ", self.outputModelSelector) # # Advanced area # self.advancedCollapsibleButton = ctk.ctkCollapsibleButton() self.advancedCollapsibleButton.text = "Advanced" self.advancedCollapsibleButton.collapsed = True self.layout.addWidget(self.advancedCollapsibleButton) advancedFormLayout = qt.QFormLayout(self.advancedCollapsibleButton) self.cleaverAdditionalParametersWidget = qt.QLineEdit() self.cleaverAdditionalParametersWidget.setToolTip('Increase --scale parameter value to generate a finer resolution mesh. See description of all parameters in module documentation (Help & Acknowledgment section).') advancedFormLayout.addRow("Cleaver meshing options:", self.cleaverAdditionalParametersWidget) self.cleaverAdditionalParametersWidget.text = "--scale 0.2 --multiplier 2 --grading 5" self.cleaverRemoveBackgroundMeshCheckBox = qt.QCheckBox(" ") self.cleaverRemoveBackgroundMeshCheckBox.checked = True self.cleaverRemoveBackgroundMeshCheckBox.setToolTip("Remove background mesh (filling segmentation reference geometry box).") advancedFormLayout.addRow("Cleaver remove background mesh:", self.cleaverRemoveBackgroundMeshCheckBox) self.cleaverPaddingPercentSpinBox = qt.QSpinBox() self.cleaverPaddingPercentSpinBox.maximum = 200 self.cleaverPaddingPercentSpinBox.value = 10 self.cleaverPaddingPercentSpinBox.suffix=" %" self.cleaverPaddingPercentSpinBox.setToolTip("Add padding around the segments to ensure some minimum thickness to the background mesh. Increase value if segments have extrusions towards the edge of the padded bounding box.") advancedFormLayout.addRow("Cleaver background padding:", self.cleaverPaddingPercentSpinBox) customCleaverPath = self.logic.getCustomCleaverPath() self.customCleaverPathSelector = ctk.ctkPathLineEdit() self.customCleaverPathSelector.setCurrentPath(customCleaverPath) self.customCleaverPathSelector.nameFilters = [self.logic.cleaverFilename] self.customCleaverPathSelector.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred) self.customCleaverPathSelector.setToolTip("Set cleaver-cli executable path. " "If value is empty then cleaver-cli bundled with this extension will be used.") advancedFormLayout.addRow("Custom Cleaver executable path:", self.customCleaverPathSelector) self.tetGenAdditionalParametersWidget = qt.QLineEdit() self.tetGenAdditionalParametersWidget.setToolTip('See description of parameters in module documentation (Help & Acknowledgment section).') advancedFormLayout.addRow("TetGen meshing options:", self.tetGenAdditionalParametersWidget) self.tetGenAdditionalParametersWidget.text = "" customTetGenPath = self.logic.getCustomTetGenPath() self.customTetGenPathSelector = ctk.ctkPathLineEdit() self.customTetGenPathSelector.setCurrentPath(customTetGenPath) self.customTetGenPathSelector.nameFilters = [self.logic.tetGenFilename] self.customTetGenPathSelector.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred) self.customTetGenPathSelector.setToolTip("Set tetgen executable path. " "If value is empty then tetgen bundled with this extension will be used.") advancedFormLayout.addRow("Custom TetGen executable path:", self.customTetGenPathSelector) self.showDetailedLogDuringExecutionCheckBox = qt.QCheckBox(" ") self.showDetailedLogDuringExecutionCheckBox.checked = False self.showDetailedLogDuringExecutionCheckBox.setToolTip("Show detailed log during model generation.") advancedFormLayout.addRow("Show detailed log:", self.showDetailedLogDuringExecutionCheckBox) self.keepTemporaryFilesCheckBox = qt.QCheckBox(" ") self.keepTemporaryFilesCheckBox.checked = False self.keepTemporaryFilesCheckBox.setToolTip("Keep temporary files (inputs, computed outputs, logs) after the model generation is completed.") self.showTemporaryFilesFolderButton = qt.QPushButton("Show temp folder") self.showTemporaryFilesFolderButton.toolTip = "Open the folder where temporary files are stored." self.showTemporaryFilesFolderButton.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.Preferred) hbox = qt.QHBoxLayout() hbox.addWidget(self.keepTemporaryFilesCheckBox) hbox.addWidget(self.showTemporaryFilesFolderButton) advancedFormLayout.addRow("Keep temporary files:", hbox) # # Display # displayParametersCollapsibleButton = ctk.ctkCollapsibleButton() displayParametersCollapsibleButton.text = "Display" displayParametersCollapsibleButton.collapsed = True self.layout.addWidget(displayParametersCollapsibleButton) displayParametersFormLayout = qt.QFormLayout(displayParametersCollapsibleButton) self.clipNodeWidget=slicer.qMRMLClipNodeWidget() clipNode = slicer.mrmlScene.GetFirstNodeByClass("vtkMRMLClipModelsNode") self.clipNodeWidget.setMRMLClipNode(clipNode) displayParametersFormLayout.addRow(self.clipNodeWidget) # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Run the algorithm." self.applyButton.enabled = False self.layout.addWidget(self.applyButton) self.statusLabel = qt.QPlainTextEdit() self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse) self.statusLabel.setCenterOnScroll(True) self.layout.addWidget(self.statusLabel) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.showTemporaryFilesFolderButton.connect('clicked(bool)', self.onShowTemporaryFilesFolder) self.inputModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.updateMRMLFromGUI) self.outputModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.updateMRMLFromGUI) self.methodSelectorComboBox.connect("currentIndexChanged(int)", self.updateMRMLFromGUI) # Immediately update deleteTemporaryFiles in the logic to make it possible to decide to # keep the temporary file while the model generation is running self.keepTemporaryFilesCheckBox.connect("toggled(bool)", self.onKeepTemporaryFilesToggled) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.updateMRMLFromGUI()
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) self.meshDirectory = ctk.ctkPathLineEdit() self.meshDirectory.filters = ctk.ctkPathLineEdit.Dirs self.meshDirectory.setToolTip("Select directory containing landmarks") parametersFormLayout.addRow("Mesh directory: ", self.meshDirectory) self.landmarkDirectory = ctk.ctkPathLineEdit() self.landmarkDirectory.filters = ctk.ctkPathLineEdit.Dirs self.landmarkDirectory.setToolTip("Select directory containing meshes") parametersFormLayout.addRow("Landmark directory: ", self.landmarkDirectory) self.gridFile = ctk.ctkPathLineEdit() self.gridFile.filters = ctk.ctkPathLineEdit().Files self.gridFile.setToolTip( "Select file specifying semi-landmark connectivity") parametersFormLayout.addRow("Grid connectivity file: ", self.gridFile) # Select output directory self.outputDirectory = ctk.ctkPathLineEdit() self.outputDirectory.filters = ctk.ctkPathLineEdit.Dirs self.outputDirectory.setToolTip("Select directory for output models: ") parametersFormLayout.addRow("Output directory: ", self.outputDirectory) # # set sample rate value # self.sampleRate = ctk.ctkDoubleSpinBox() self.sampleRate.singleStep = 1 self.sampleRate.minimum = 1 self.sampleRate.maximum = 100 self.sampleRate.setDecimals(0) self.sampleRate.value = 10 self.sampleRate.setToolTip( "Select sample rate for semi-landmark interpolation") parametersFormLayout.addRow("Sample rate for interpolation:", self.sampleRate) # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Generate PlaceSemiLMPatchess." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # connections self.meshDirectory.connect('validInputChanged(bool)', self.onSelect) self.landmarkDirectory.connect('validInputChanged(bool)', self.onSelect) self.gridFile.connect('validInputChanged(bool)', self.onSelect) self.outputDirectory.connect('validInputChanged(bool)', self.onSelect) self.applyButton.connect('clicked(bool)', self.onApplyButton) # Add vertical spacer self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # Reload and Test area # reloadCollapsibleButton = ctk.ctkCollapsibleButton() reloadCollapsibleButton.text = "Reload && Test" reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton) # reload button # (use this during development, but remove it when delivering # your module to users) self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "Freehand3DUltrasound Reload" reloadFormLayout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # uncomment the following line for debug/development. self.layout.addWidget(reloadCollapsibleButton) # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) self.jsonFindingsPath = ctk.ctkPathLineEdit() self.jsonFindingsPath.currentPath = '/home/mehrtash/github/ProstateX/notebooks/findings.json' # self.dockerPath.setMaximumWidth(300) parametersFormLayout.addRow("Findings File Path:", self.jsonFindingsPath) # # Load Button # self.loadButton = qt.QPushButton("Load") self.loadButton.toolTip = "Run the algorithm." self.loadButton.enabled = False parametersFormLayout.addRow(self.loadButton) # # finding index # self.findingIndexSliderWidget = ctk.ctkSliderWidget() self.findingIndexSliderWidget.singleStep = 1 self.findingIndexSliderWidget.minimum = 0 self.findingIndexSliderWidget.maximum = 10 self.findingIndexSliderWidget.setDecimals(0) self.findingIndexSliderWidget.enabled = False self.findingIndexSliderWidget.setToolTip( "Set threshold value for computing the output image. Voxels that have intensities lower than this value will set to zero." ) parametersFormLayout.addRow("Finding Index: ", self.findingIndexSliderWidget) # zone line edit self.uidLineEdit = qt.QLineEdit() self.uidLineEdit.setReadOnly(True) parametersFormLayout.addRow("Zone:", self.uidLineEdit) # zone line edit self.zoneLineEdit = qt.QLineEdit() self.zoneLineEdit.setReadOnly(True) parametersFormLayout.addRow("Zone:", self.zoneLineEdit) # zone line edit self.clinSigLineEdit = qt.QLineEdit() self.clinSigLineEdit.setReadOnly(True) parametersFormLayout.addRow("Clinical Significance:", self.clinSigLineEdit) # connections self.loadButton.connect('clicked(bool)', self.onLoadButton) self.jsonFindingsPath.connect("currentPathChanged(QString)", self.onSelect) self.findingIndexSliderWidget.connect('valueChanged(double)', self.findingIndexChanged) # Add vertical spacer self.layout.addStretch(1) # Refresh Load button state self.onSelect()