def setup(self): # this is the function that implements all GUI ScriptedLoadableModuleWidget.setup(self) # This sets the view being used to the red view only slicer.app.layoutManager().setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUpRedSliceView) l = slicer.modules.createmodels.logic() self.needleModel = l.CreateNeedle(150, 0.4, 0, False) #This code block creates a collapsible button #This defines which type of button you are using self.usContainer = ctk.ctkCollapsibleButton() #This is what the button will say self.usContainer.text = "Ultrasound Information" #Thiss actually creates that button self.layout.addWidget(self.usContainer) #This creates a variable that describes layout within this collapsible button self.usLayout = qt.QFormLayout(self.usContainer) #This descirbes the type of widget self.inputIPLineEdit = qt.QLineEdit() #This sets a placehoder example of what should be inputted to the line edit self.inputIPLineEdit.setPlaceholderText("127.0.0.1") #This is the help tooltip self.inputIPLineEdit.toolTip = "Put the IP address of your ultrasound device here" #This is the text that is input inot the line self.IPLabel = qt.QLabel("Server IP:") if slicer.mrmlScene.GetNodesByClass("vtkMRMLSequenceNode").GetNumberOfItems() == 0: self.usLayout.addRow(self.IPLabel, self.inputIPLineEdit) #This code block is the exact same as the one above only it asks for the server port self.layout.addWidget(self.usContainer) self.inputPortLineEdit = qt.QLineEdit() self.inputPortLineEdit.setPlaceholderText("18944") self.inputPortLineEdit.setValidator(qt.QIntValidator()) self.inputPortLineEdit.toolTip = "Put the Port of your ultrasound device here" self.portLabel = qt.QLabel("Sever Port:") if slicer.mrmlScene.GetNodesByClass("vtkMRMLSequenceNode").GetNumberOfItems() == 0: self.usLayout.addRow(self.portLabel, self.inputPortLineEdit) #This is a push button self.connectButton = qt.QPushButton() self.connectButton.setDefault(False) #This button says connect self.connectButton.text = "Connect" #help tooltip that explains the funciton self.connectButton.toolTip = "Connects to Ultrasound" #adds the widget to the layout if slicer.mrmlScene.GetNodesByClass("vtkMRMLSequenceNode").GetNumberOfItems() == 0: self.usLayout.addWidget(self.connectButton) # Combobox for image selection self.imageSelector = slicer.qMRMLNodeComboBox() self.imageSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] self.imageSelector.selectNodeUponCreation = True self.imageSelector.addEnabled = False self.imageSelector.removeEnabled = False self.imageSelector.noneEnabled = True self.imageSelector.showHidden = False self.imageSelector.showChildNodeTypes = False self.imageSelector.setMRMLScene( slicer.mrmlScene ) self.imageSelector.setToolTip( "Pick the image to be used." ) self.usLayout.addRow("US Volume: ", self.imageSelector) #add combo box for linear transform node self.TransformSelector = slicer.qMRMLNodeComboBox() self.TransformSelector.nodeTypes = ["vtkMRMLLinearTransformNode"] self.TransformSelector.selectNodeUponCreation = True self.TransformSelector.addEnabled = False self.TransformSelector.removeEnabled = False self.TransformSelector.noneEnabled = True self.TransformSelector.showHidden = False self.TransformSelector.showChildNodeTypes = False self.TransformSelector.setMRMLScene( slicer.mrmlScene ) self.TransformSelector.setToolTip( "Pick the transform representing the straw line." ) self.usLayout.addRow("Tip to Probe: ", self.TransformSelector) self.calibrationContainer = ctk.ctkCollapsibleButton() #This is what the button will say self.calibrationContainer.text = "Calibration Parameters" #Thiss actually creates that button self.layout.addWidget(self.calibrationContainer) #This creates a variable that describes layout within this collapsible button self.calibrationLayout = qt.QFormLayout(self.calibrationContainer) self.segLabel = qt.QLabel() self.calibrationLayout.addRow(qt.QLabel("Type of segmentation:"), self.segLabel) self.recordContainer = ctk.ctkCollapsibleButton() #This is what the button will say self.recordContainer.text = "Recording Options" #Thiss actually creates that button #This creates a variable that describes layout within this collapsible button self.recordLayout = qt.QFormLayout(self.recordContainer) self.RecordButton = qt.QPushButton() self.RecordButton.text = "Start Recording" self.recordLayout.addWidget(self.RecordButton) self.StopRecordButton = qt.QPushButton() self.StopRecordButton.text = "Stop Recording" self.recordLayout.addWidget(self.StopRecordButton) self.pathInput = qt.QLineEdit() self.pathInput.setPlaceholderText("Enter the path to save files to") self.pathText = qt.QLabel("File Path:") self.recordLayout.addRow(self.pathText, self.pathInput) self.SaveRecordButton = qt.QPushButton() self.SaveRecordButton.text = "Save Recording" self.recordLayout.addWidget(self.SaveRecordButton) # This creates another collapsible button self.fiducialContainer = ctk.ctkCollapsibleButton() self.fiducialContainer.text = "Registration" self.fiducialLayout = qt.QFormLayout(self.fiducialContainer) #This is the exact same as the code block below but it freezes the US to capture a screenshot self.freezeButton = qt.QPushButton() if slicer.mrmlScene.GetNodesByClass("vtkMRMLSequenceNode").GetNumberOfItems() == 0: self.freezeButton.text = "Freeze" else: self.freezeButton.text = "Place Fiducial" self.freezeButton.toolTip = "Freeze the ultrasound image for fiducial placement" self.fiducialLayout.addRow(self.freezeButton) self.shortcut = qt.QShortcut(qt.QKeySequence('f'), slicer.util.mainWindow()) self.numFidLabel = qt.QLabel() self.fiducialLayout.addRow(qt.QLabel("Fiducials collected:"), self.numFidLabel) self.transformTable = qt.QTableWidget() self.transTableItem = qt.QTableWidgetItem() self.fidError = qt.QLabel() self.transformTable.setRowCount(4) self.transformTable.setColumnCount(4) self.transformTable.horizontalHeader().hide() self.transformTable.verticalHeader().hide() self.transformTable.setItem(0,0, qt.QTableWidgetItem("1")) self.transformTable.setItem(0,1, qt.QTableWidgetItem("0")) self.transformTable.setItem(0,2, qt.QTableWidgetItem("0")) self.transformTable.setItem(0,3, qt.QTableWidgetItem("0")) self.transformTable.setItem(1,0, qt.QTableWidgetItem("0")) self.transformTable.setItem(1,1, qt.QTableWidgetItem("1")) self.transformTable.setItem(1,2, qt.QTableWidgetItem("0")) self.transformTable.setItem(1,3, qt.QTableWidgetItem("0")) self.transformTable.setItem(2,0, qt.QTableWidgetItem("0")) self.transformTable.setItem(2,1, qt.QTableWidgetItem("0")) self.transformTable.setItem(2,2, qt.QTableWidgetItem("1")) self.transformTable.setItem(2,3, qt.QTableWidgetItem("0")) self.transformTable.setItem(3,0, qt.QTableWidgetItem("0")) self.transformTable.setItem(3,1, qt.QTableWidgetItem("0")) self.transformTable.setItem(3,2, qt.QTableWidgetItem("0")) self.transformTable.setItem(3,3, qt.QTableWidgetItem("1")) self.transformTable.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.MinimumExpanding) self.copyIcon =qt.QIcon(":Icons/Medium/SlicerEditCopy.png") self.copyButton = qt.QPushButton() self.copyButton.setIcon(self.copyIcon) self.copyButton.toolTip = "Copy" self.copyButton.setMaximumWidth(64) self.copyHbox = qt.QHBoxLayout() self.copyHbox.addWidget(self.copyButton) self.copyButton.enabled = False if self.numFidLabel >= 2: self.copyButton.enabled = True self.fiducialLayout.addRow(qt.QLabel("Image to probe transform:")) self.fiducialLayout.addRow(self.transformTable) # Add vertical spacer self.layout.addStretch(1) # Add vertical spacer self.layout.addStretch(1) self.fiducialLayout.addRow("Copy:", self.copyHbox) self.validationContainer = ctk.ctkCollapsibleButton() self.validationContainer.text = "Validation" self.validationLayout = qt.QFormLayout(self.validationContainer) self.visualizeButton = qt.QPushButton('Show 3D Scene') self.visualizeButton.toolTip = "This button enables the 3D view for visual validation" self.validationLayout.addRow(self.visualizeButton) self.visualizeButton.connect('clicked(bool)', self.onVisualizeButtonClicked) self.resetButton = qt.QPushButton('Reset') self.resetButton.setDefault(False) self.resetButton.toolTip = "This Button Resets the Module" self.validationLayout.addRow(self.resetButton) # Add the containers to the parent self.layout.addWidget(self.usContainer) self.layout.addWidget(self.calibrationContainer) if slicer.mrmlScene.GetNodesByClass("vtkMRMLSequenceNode").GetNumberOfItems() == 0: self.layout.addWidget(self.recordContainer) self.layout.addWidget(self.fiducialContainer) #self.layout.addWidget(self.transformContainer) self.layout.addWidget(self.validationContainer) # Add vertical spacer self.layout.addStretch(1) # Connections if slicer.mrmlScene.GetNodesByClass("vtkMRMLSequenceNode").GetNumberOfItems() == 0: self.connectButton.connect('clicked(bool)', self.onConnectButtonClicked) self.freezeButton.connect('clicked(bool)', self.onConnectButtonClicked) self.shortcut.connect('activated()', self.onConnectButtonClicked) else: self.shortcut.connect('activated()', self.onFiducialClicked) self.freezeButton.connect('clicked(bool)', self.onFiducialClicked) self.RecordButton.connect('clicked(bool)', self.onRecordButtonClicked) self.StopRecordButton.connect('clicked(bool)', self.onStopRecordButtonClicked) self.SaveRecordButton.connect('clicked(bool)', self.onSaveRecordButtonClicked) self.copyButton.connect('clicked(bool)', self.onCopyButtonClicked) self.inputIPLineEdit.connect('textChanged(QString)', self.onInputChanged) self.inputPortLineEdit.connect('textChanged(QString)', self.onInputChanged) self.imageSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onImageChanged) self.TransformSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onTransformChanged) self.resetButton.connect('clicked(bool)', self.onResetButtonClicked) # Disable buttons until conditions are met self.connectButton.setEnabled(True) if slicer.mrmlScene.GetNodesByClass("vtkMRMLSequenceNode").GetNumberOfItems() == 0: self.freezeButton.setEnabled(False) self.StopRecordButton.setEnabled(False) self.sceneObserverTag = slicer.mrmlScene.AddObserver(slicer.mrmlScene.NodeAddedEvent, self.onNodeAdded)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # Input file # Text + Button invoking QFileDialog self.inputFileLayout = qt.QHBoxLayout() self.inputFileLabelHeader = qt.QLabel() self.inputFileLabelHeader.text = "Input File: " self.inputFileLabelFile = qt.QLabel() self.inputFileLabelFile.text = "Input header.xml or .m3d" self.inputFileButton = qt.QPushButton() self.inputFileButton.text = "Browse" self.inputFileLayout.addWidget(self.inputFileLabelHeader) self.inputFileLayout.addWidget(self.inputFileLabelFile) self.inputFileLayout.addWidget(self.inputFileButton) self.layout.addLayout(self.inputFileLayout) # # Parameters Area # self.parametersCollapsibleButton = ctk.ctkCollapsibleButton() self.parametersCollapsibleButton.collapsed = True self.parametersCollapsibleButton.text = "Parameters for legacy m3d format" self.layout.addWidget(self.parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(self.parametersCollapsibleButton) # set distance of fold curve from interior points self.distSlider = slicer.qMRMLSliderWidget() self.distSlider.setProperty('maximum', 0.6) self.distSlider.setProperty('minimum', 0.0) self.distSlider.setProperty('singleStep', 0.01) self.distSlider.setToolTip( "Parameter used in transformation from legacy s-rep to new s-rep") parametersFormLayout.addRow("Set distance to expand fold curve", self.distSlider) self.outputFolderLayout = qt.QHBoxLayout() self.outputFolderLabelHeader = qt.QLabel() self.outputFolderLabelHeader.text = "Output folder: " self.outputFolderLabelFile = qt.QLabel() self.outputFolderLabelFile.text = "Folder to save the new xml format" self.outputFolderButton = qt.QPushButton() self.outputFolderButton.text = "Browse" self.outputFolderLayout.addWidget(self.outputFolderLabelHeader) self.outputFolderLayout.addWidget(self.outputFolderLabelFile) self.outputFolderLayout.addWidget(self.outputFolderButton) parametersFormLayout.addRow(self.outputFolderLayout) # # Apply Button # self.applyButton = qt.QPushButton("Visualize s-rep file") self.applyButton.toolTip = "Parse and visualize s-rep." self.layout.addWidget(self.applyButton) # Unused # self.boundarySurfaceRendering = qt.QCheckBox() # self.boundarySurfaceRendering.checked = 0 # self.boundarySurfaceRendering.setToolTip("If checked, set the visibility of the boundary mesh") # self.layout.addWidget(self.boundarySurfaceRendering) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.inputFileButton.connect('clicked(bool)', self.onInputFileButtonClicked) self.outputFolderButton.connect('clicked(bool)', self.onOutputFolderButtonClicked) # 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('See description of parameters in module documentation ') advancedFormLayout.addRow("Cleaver meshing options:", self.cleaverAdditionalParametersWidget) self.cleaverAdditionalParametersWidget.text = "--scale 0.2 --multiplier 2 --grading 5" self.tetGenAdditionalParametersWidget = qt.QLineEdit() self.tetGenAdditionalParametersWidget.setToolTip('See description of parameters in module documentation ') advancedFormLayout.addRow("TetGen meshing options:", self.tetGenAdditionalParametersWidget) self.tetGenAdditionalParametersWidget.text = "" 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) 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) 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) # # 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 setupOptionsFrame(self): self.thresholdSliderLabel = qt.QLabel("Threshold Range:") self.thresholdSliderLabel.setToolTip( "Set the range of the background values that should be labeled.") self.scriptedEffect.addOptionsWidget(self.thresholdSliderLabel) self.thresholdSlider = ctk.ctkRangeWidget() self.thresholdSlider.spinBoxAlignment = qt.Qt.AlignTop self.thresholdSlider.singleStep = 0.01 self.scriptedEffect.addOptionsWidget(self.thresholdSlider) self.autoThresholdMethodSelectorComboBox = qt.QComboBox() self.autoThresholdMethodSelectorComboBox.addItem("Otsu", METHOD_OTSU) self.autoThresholdMethodSelectorComboBox.addItem("Huang", METHOD_HUANG) self.autoThresholdMethodSelectorComboBox.addItem( "IsoData", METHOD_ISO_DATA) self.autoThresholdMethodSelectorComboBox.addItem( "Kittler-Illingworth", METHOD_KITTLER_ILLINGWORTH) self.autoThresholdMethodSelectorComboBox.addItem("Li", METHOD_LI) self.autoThresholdMethodSelectorComboBox.addItem( "Maximum entropy", METHOD_MAXIMUM_ENTROPY) self.autoThresholdMethodSelectorComboBox.addItem( "Moments", METHOD_MOMENTS) self.autoThresholdMethodSelectorComboBox.addItem( "Renyi entropy", METHOD_RENYI_ENTROPY) self.autoThresholdMethodSelectorComboBox.addItem( "Shanbhag", METHOD_SHANBHAG) self.autoThresholdMethodSelectorComboBox.addItem( "Triangle", METHOD_TRIANGLE) self.autoThresholdMethodSelectorComboBox.addItem("Yen", METHOD_YEN) self.autoThresholdMethodSelectorComboBox.setToolTip( "Select method to compute threshold value automatically.") self.autoThresholdModeSelectorComboBox = qt.QComboBox() self.autoThresholdModeSelectorComboBox.addItem("set auto->maximum", MODE_SET_LOWER_MAX) self.autoThresholdModeSelectorComboBox.addItem("set minimum->auto", MODE_SET_MIN_UPPER) self.autoThresholdModeSelectorComboBox.addItem("set as lower", MODE_SET_LOWER) self.autoThresholdModeSelectorComboBox.addItem("set as upper", MODE_SET_UPPER) self.autoThresholdMethodSelectorComboBox.setToolTip( "How to set lower and upper threshold values. Current refers to keeping the current value." ) self.selectNextAutoThresholdButton = qt.QPushButton(">") self.selectNextAutoThresholdButton.setToolTip( "Select next thresholding method and set thresholds using that." + " Useful for iterating through all available methods.") self.setAutoThresholdButton = qt.QPushButton("Set") self.setAutoThresholdButton.setToolTip( "Compute automatic threshold and set as threshold limit.") # qt.QSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding) # fails on some systems, therefore set the policies using separate method calls qSize = qt.QSizePolicy() qSize.setHorizontalPolicy(qt.QSizePolicy.Expanding) self.setAutoThresholdButton.setSizePolicy(qSize) autoThresholdFrame = qt.QHBoxLayout() autoThresholdFrame.addWidget(self.autoThresholdMethodSelectorComboBox) autoThresholdFrame.addWidget(self.autoThresholdModeSelectorComboBox) autoThresholdFrame.addWidget(self.selectNextAutoThresholdButton) autoThresholdFrame.addWidget(self.setAutoThresholdButton) self.scriptedEffect.addLabeledOptionsWidget("Automatic threshold:", autoThresholdFrame) self.useForPaintButton = qt.QPushButton("Use for masking") self.useForPaintButton.setToolTip( "Use specified intensity range for masking and switch to Paint effect." ) self.scriptedEffect.addOptionsWidget(self.useForPaintButton) self.applyButton = qt.QPushButton("Apply") self.applyButton.objectName = self.__class__.__name__ + 'Apply' self.applyButton.setToolTip( "Fill selected segment in regions that are in the specified intensity range." ) self.scriptedEffect.addOptionsWidget(self.applyButton) self.useForPaintButton.connect('clicked()', self.onUseForPaint) self.thresholdSlider.connect('valuesChanged(double,double)', self.onThresholdValuesChanged) self.autoThresholdMethodSelectorComboBox.connect( "currentIndexChanged(int)", self.updateMRMLFromGUI) self.autoThresholdModeSelectorComboBox.connect( "currentIndexChanged(int)", self.updateMRMLFromGUI) self.selectNextAutoThresholdButton.connect( 'clicked()', self.onSelectNextAutoThresholdMethod) self.setAutoThresholdButton.connect('clicked()', self.onAutoThreshold) self.applyButton.connect('clicked()', self.onApply)
def buildInterface(self): self.layout = qt.QHBoxLayout(self) self.titleLabel = QubLabel("<B>Title<B>", self) self.titleLabel.setAlignment(qt.Qt.AlignCenter) self.titleLabel.setSizePolicy( qt.QSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Fixed)) self.layout.addWidget(self.titleLabel) """ move and configure appearence """ self.radioGroup = QubRadioGroup(QubRadioGroup.Horizontal, self) self.radioGroup.hide() self.connect(self.radioGroup, qt.PYSIGNAL("PositionClicked"), self.positionClicked) self.layout.addWidget(self.radioGroup) self.setButton = qt.QPushButton("Set", self) self.setButton.hide() self.connect(self.setButton, qt.SIGNAL("clicked()"), self.setPosition) self.setButton.setEnabled(False) self.layout.addWidget(self.setButton) """ display appearence """ self.valueLabel = qt.QLabel("no value", self) self.valueLabel.hide() self.valueLabel.setAlignment(qt.Qt.AlignCenter) self.layout.addWidget(self.valueLabel) """ incremental appearence """ self.frame = qt.QFrame(self) self.frame.hide() self.frame.setFrameShape(qt.QFrame.NoFrame) self.frame.setFrameShadow(qt.QFrame.Plain) self.layout.addWidget(self.frame) vlayout = qt.QVBoxLayout(self.frame) vlayout.setMargin(10) self.valueWidget = QubValue(self.frame, titleType=QubValue.Label, valueType=QubValue.Label, orientation=QubValue.Horizontal) self.valueWidget.setTitle("Current Position") vlayout.addWidget(self.valueWidget) vlayout.addSpacing(5) hlayout = qt.QHBoxLayout(vlayout) self.positionList = qt.QListBox(self.frame) hlayout.addWidget(self.positionList) hlayout.addSpacing(5) vlayout1 = qt.QVBoxLayout(hlayout) self.gotoButton = qt.QPushButton("Go", self.frame) self.connect(self.gotoButton, qt.SIGNAL("clicked()"), self.gotoPosition) vlayout1.addWidget(self.gotoButton) vlayout1.addStretch(1) self.addButton = qt.QPushButton("Add", self.frame) self.connect(self.addButton, qt.SIGNAL("clicked()"), self.addPosition) vlayout1.addWidget(self.addButton) vlayout1.addSpacing(5) self.remButton = qt.QPushButton("Delete", self.frame) self.connect(self.remButton, qt.SIGNAL("clicked()"), self.remPosition) vlayout1.addWidget(self.remButton) """ popup config """ self.configWindow = MultiplePositionConfigurator(self) self.popupMenu = qt.QPopupMenu(self.titleLabel) self.popupMenu.insertItem("Configure", self.configWindow.show)
def setupOptionsFrame(self): self.thresholdSliderLabel = qt.QLabel("Threshold Range:") self.thresholdSliderLabel.setToolTip( "Set the range of the background values that should be labeled.") self.scriptedEffect.addOptionsWidget(self.thresholdSliderLabel) self.thresholdSlider = ctk.ctkRangeWidget() self.thresholdSlider.spinBoxAlignment = qt.Qt.AlignTop self.thresholdSlider.singleStep = 0.01 self.scriptedEffect.addOptionsWidget(self.thresholdSlider) self.autoThresholdModeSelectorComboBox = qt.QComboBox() self.autoThresholdModeSelectorComboBox.addItem("auto->maximum", MODE_SET_LOWER_MAX) self.autoThresholdModeSelectorComboBox.addItem("minimum->auto", MODE_SET_MIN_UPPER) self.autoThresholdModeSelectorComboBox.addItem("as lower", MODE_SET_LOWER) self.autoThresholdModeSelectorComboBox.addItem("as upper", MODE_SET_UPPER) self.autoThresholdModeSelectorComboBox.setToolTip( "How to set lower and upper threshold values. Current refers to keeping the current value." ) self.autoThresholdMethodSelectorComboBox = qt.QComboBox() self.autoThresholdMethodSelectorComboBox.addItem("Otsu", METHOD_OTSU) self.autoThresholdMethodSelectorComboBox.addItem("Huang", METHOD_HUANG) self.autoThresholdMethodSelectorComboBox.addItem( "IsoData", METHOD_ISO_DATA) # Kittler-Illingworth sometimes fails with an exception, but it does not cause any major issue, # it just logs an error message and does not compute a new threshold value self.autoThresholdMethodSelectorComboBox.addItem( "Kittler-Illingworth", METHOD_KITTLER_ILLINGWORTH) # Li sometimes crashes (index out of range error in # ITK/Modules/Filtering/Thresholding/include/itkLiThresholdCalculator.hxx#L94) # We can add this method back when issue is fixed in ITK. #self.autoThresholdMethodSelectorComboBox.addItem("Li", METHOD_LI) self.autoThresholdMethodSelectorComboBox.addItem( "Maximum entropy", METHOD_MAXIMUM_ENTROPY) self.autoThresholdMethodSelectorComboBox.addItem( "Moments", METHOD_MOMENTS) self.autoThresholdMethodSelectorComboBox.addItem( "Renyi entropy", METHOD_RENYI_ENTROPY) self.autoThresholdMethodSelectorComboBox.addItem( "Shanbhag", METHOD_SHANBHAG) self.autoThresholdMethodSelectorComboBox.addItem( "Triangle", METHOD_TRIANGLE) self.autoThresholdMethodSelectorComboBox.addItem("Yen", METHOD_YEN) self.autoThresholdMethodSelectorComboBox.setToolTip( "Select method to compute threshold value automatically.") self.selectPreviousAutoThresholdButton = qt.QToolButton() self.selectPreviousAutoThresholdButton.text = "<" self.selectPreviousAutoThresholdButton.setToolTip( "Select previous thresholding method and set thresholds." + " Useful for iterating through all available methods.") self.selectNextAutoThresholdButton = qt.QToolButton() self.selectNextAutoThresholdButton.text = ">" self.selectNextAutoThresholdButton.setToolTip( "Select next thresholding method and set thresholds." + " Useful for iterating through all available methods.") self.setAutoThresholdButton = qt.QPushButton("Set") self.setAutoThresholdButton.setToolTip( "Set threshold using selected method.") # qt.QSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding) # fails on some systems, therefore set the policies using separate method calls qSize = qt.QSizePolicy() qSize.setHorizontalPolicy(qt.QSizePolicy.Expanding) self.setAutoThresholdButton.setSizePolicy(qSize) autoThresholdFrame = qt.QHBoxLayout() autoThresholdFrame.addWidget(self.autoThresholdModeSelectorComboBox) autoThresholdFrame.addWidget(self.autoThresholdMethodSelectorComboBox) autoThresholdFrame.addWidget(self.selectPreviousAutoThresholdButton) autoThresholdFrame.addWidget(self.selectNextAutoThresholdButton) autoThresholdFrame.addWidget(self.setAutoThresholdButton) self.scriptedEffect.addLabeledOptionsWidget("Automatic threshold:", autoThresholdFrame) self.useForPaintButton = qt.QPushButton("Use for masking") self.useForPaintButton.setToolTip( "Use specified intensity range for masking and switch to Paint effect." ) self.scriptedEffect.addOptionsWidget(self.useForPaintButton) self.applyButton = qt.QPushButton("Apply") self.applyButton.objectName = self.__class__.__name__ + 'Apply' self.applyButton.setToolTip( "Fill selected segment in regions that are in the specified intensity range." ) self.scriptedEffect.addOptionsWidget(self.applyButton) self.useForPaintButton.connect('clicked()', self.onUseForPaint) self.thresholdSlider.connect('valuesChanged(double,double)', self.onThresholdValuesChanged) self.autoThresholdMethodSelectorComboBox.connect( "activated(int)", self.onSelectedAutoThresholdMethod) self.autoThresholdModeSelectorComboBox.connect( "activated(int)", self.onSelectedAutoThresholdMethod) self.selectPreviousAutoThresholdButton.connect( 'clicked()', self.onSelectPreviousAutoThresholdMethod) self.selectNextAutoThresholdButton.connect( 'clicked()', self.onSelectNextAutoThresholdMethod) self.setAutoThresholdButton.connect('clicked()', self.onAutoThreshold) self.applyButton.connect('clicked()', self.onApply)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # File area # filesCollapsibleButton = ctk.ctkCollapsibleButton() filesCollapsibleButton.text = "Input files" filesCollapsibleButton.collapsed = False self.layout.addWidget(filesCollapsibleButton) # Layout within the files collapsible button filesFormLayout = qt.QFormLayout(filesCollapsibleButton) # select one file buttonLayout = qt.QHBoxLayout() self.archetypeText = qt.QLineEdit() buttonLayout.addWidget(self.archetypeText) self.addFromArchetype = qt.QPushButton("Browse...") buttonLayout.addWidget(self.addFromArchetype) self.archetypeStartNumber = 0 filesFormLayout.addRow("Filename pattern: ", buttonLayout) # file list group fileListGroupBox = ctk.ctkCollapsibleGroupBox() fileListGroupBox.title = "File list" fileListLayout = qt.QVBoxLayout() fileListGroupBox.setLayout(fileListLayout) filesFormLayout.addRow("", fileListGroupBox) self.addByBrowsingButton = qt.QPushButton("Select files...") fileListLayout.addWidget(self.addByBrowsingButton) self.fileTable = qt.QTextBrowser() fileListLayout.addWidget(self.fileTable) fileListGroupBox.collapsed = True # original volume size self.originalVolumeSizeLabel = qt.QLabel() filesFormLayout.addRow("Size: ", self.originalVolumeSizeLabel) # reverse slice order self.reverseCheckBox = qt.QCheckBox() self.reverseCheckBox.toolTip = "Read the images in reverse order (flips loaded volume along IS axis)" filesFormLayout.addRow("Reverse: ", self.reverseCheckBox) # original spacing self.spacingWidget = slicer.qMRMLCoordinatesWidget() self.spacingWidget.setMRMLScene(slicer.mrmlScene) self.spacingWidget.decimalsOption = ctk.ctkDoubleSpinBox.DecimalsByKey | ctk.ctkDoubleSpinBox.DecimalsByShortcuts | ctk.ctkDoubleSpinBox.DecimalsByValue self.spacingWidget.minimum = 0.0 self.spacingWidget.maximum = 1000000000.0 self.spacingWidget.quantity = "length" self.spacingWidget.unitAwareProperties = slicer.qMRMLCoordinatesWidget.Precision | slicer.qMRMLCoordinatesWidget.Prefix | slicer.qMRMLCoordinatesWidget.Scaling | slicer.qMRMLCoordinatesWidget.Suffix self.spacingWidget.coordinates = "1,1,1" self.spacingWidget.toolTip = "Set the colunm, row, slice spacing; original spacing not including downsample" filesFormLayout.addRow("Spacing: ", self.spacingWidget) # # 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", "vtkMRMLVectorVolumeNode" ] 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.noneDisplay = "(Create new volume)" self.outputSelector.setMRMLScene(slicer.mrmlScene) self.outputSelector.setToolTip( "Pick the output volume to populate or None to autogenerate.") outputFormLayout.addRow("Output Volume: ", self.outputSelector) # # output ROI selector # self.outputROISelector = slicer.qMRMLNodeComboBox() self.outputROISelector.nodeTypes = [ "vtkMRMLAnnotationROINode", "vtkMRMLMarkupsROINode" ] self.outputROISelector.showChildNodeTypes = False self.outputROISelector.showHidden = False self.outputROISelector.showChildNodeTypes = False self.outputROISelector.noneEnabled = True self.outputROISelector.removeEnabled = True self.outputROISelector.renameEnabled = True self.outputROISelector.addEnabled = False self.outputROISelector.noneDisplay = "(Full volume)" self.outputROISelector.setMRMLScene(slicer.mrmlScene) self.outputROISelector.setToolTip( "Set the region of the volume that will be loaded") outputFormLayout.addRow("Region of interest: ", self.outputROISelector) # # Quality selector # qualityLayout = qt.QVBoxLayout() self.qualityPreviewRadioButton = qt.QRadioButton("preview") self.qualityHalfRadioButton = qt.QRadioButton("half resolution") self.qualityFullRadioButton = qt.QRadioButton("full resolution") qualityLayout.addWidget(self.qualityPreviewRadioButton) qualityLayout.addWidget(self.qualityHalfRadioButton) qualityLayout.addWidget(self.qualityFullRadioButton) self.qualityPreviewRadioButton.setChecked(True) outputFormLayout.addRow("Quality: ", qualityLayout) self.sliceSkipSpinBox = qt.QSpinBox() self.sliceSkipSpinBox.toolTip = "Skips the selected number of slices between each pair of output volume slices (use, for example, on long thin samples with more slices than in-plane resolution)" outputFormLayout.addRow("Slice skip: ", self.sliceSkipSpinBox) # Force grayscale output self.grayscaleCheckBox = qt.QCheckBox() self.grayscaleCheckBox.toolTip = "Force reading the image in grayscale. Only makes a difference if the input has color (RGB or RGBA) voxels." self.grayscaleCheckBox.checked = True outputFormLayout.addRow("Grayscale: ", self.grayscaleCheckBox) # output volume size self.outputVolumeSizeLabel = qt.QLabel() outputFormLayout.addRow("Output size: ", self.outputVolumeSizeLabel) # output volume spacing self.outputSpacingWidget = slicer.qMRMLCoordinatesWidget() self.outputSpacingWidget.setMRMLScene(slicer.mrmlScene) self.outputSpacingWidget.readOnly = True self.outputSpacingWidget.frame = False self.outputSpacingWidget.decimalsOption = ctk.ctkDoubleSpinBox.DecimalsByKey | ctk.ctkDoubleSpinBox.DecimalsByShortcuts | ctk.ctkDoubleSpinBox.DecimalsByValue self.outputSpacingWidget.minimum = 0.0 self.outputSpacingWidget.maximum = 1000000000.0 self.outputSpacingWidget.quantity = "length" self.outputSpacingWidget.unitAwareProperties = slicer.qMRMLCoordinatesWidget.Precision | slicer.qMRMLCoordinatesWidget.Prefix | slicer.qMRMLCoordinatesWidget.Scaling | slicer.qMRMLCoordinatesWidget.Suffix self.outputSpacingWidget.coordinates = "1,1,1" self.outputSpacingWidget.toolTip = "Slice spacing of the volume that will be loaded" outputFormLayout.addRow("Output spacing: ", self.outputSpacingWidget) self.loadButton = qt.QPushButton("Load files") self.loadButton.toolTip = "Load files as a 3D volume" self.loadButton.enabled = False outputFormLayout.addRow(self.loadButton) # connections self.reverseCheckBox.connect('toggled(bool)', self.updateLogicFromWidget) self.sliceSkipSpinBox.connect("valueChanged(int)", self.updateLogicFromWidget) self.spacingWidget.connect("coordinatesChanged(double*)", self.updateLogicFromWidget) self.qualityPreviewRadioButton.connect( "toggled(bool)", lambda toggled, widget=self.qualityPreviewRadioButton: self. onQualityToggled(toggled, widget)) self.qualityHalfRadioButton.connect( "toggled(bool)", lambda toggled, widget=self.qualityHalfRadioButton: self. onQualityToggled(toggled, widget)) self.qualityFullRadioButton.connect( "toggled(bool)", lambda toggled, widget=self.qualityFullRadioButton: self. onQualityToggled(toggled, widget)) self.grayscaleCheckBox.connect('toggled(bool)', self.updateLogicFromWidget) self.outputROISelector.connect("currentNodeChanged(vtkMRMLNode*)", self.setOutputROINode) self.addByBrowsingButton.connect('clicked()', self.addByBrowsing) self.addFromArchetype.connect('clicked()', self.selectArchetype) self.archetypeText.connect('textChanged(const QString &)', self.populateFromArchetype) self.loadButton.connect('clicked()', self.onLoadButton) # Add vertical spacer self.layout.addStretch(1) self.loadButton.enabled = False
def __init__(self, *args): BaseComponents.BlissWidget.__init__(self, *args) self.addProperty("hwobj", "string", "") self.widget = CatsMaintWidgetSoleil(self) qt.QHBoxLayout(self) self.layout().addWidget(self.widget) qt.QObject.connect(self.widget.btPowerOn, qt.SIGNAL("clicked()"), self._powerOn) qt.QObject.connect( self.widget.btPowerOff, qt.SIGNAL("clicked()"), self._powerOff ) qt.QObject.connect( self.widget.btLid1Open, qt.SIGNAL("clicked()"), self._lid1Open ) qt.QObject.connect( self.widget.btLid1Close, qt.SIGNAL("clicked()"), self._lid1Close ) qt.QObject.connect( self.widget.btLid2Open, qt.SIGNAL("clicked()"), self._lid2Open ) qt.QObject.connect( self.widget.btLid2Close, qt.SIGNAL("clicked()"), self._lid2Close ) qt.QObject.connect( self.widget.btLid3Open, qt.SIGNAL("clicked()"), self._lid3Open ) qt.QObject.connect( self.widget.btLid3Close, qt.SIGNAL("clicked()"), self._lid3Close ) qt.QObject.connect( self.widget.btResetError, qt.SIGNAL("clicked()"), self._resetError ) qt.QObject.connect(self.widget.btBack, qt.SIGNAL("clicked()"), self._backTraj) qt.QObject.connect(self.widget.btSafe, qt.SIGNAL("clicked()"), self._safeTraj) # MS 2014-11-18 qt.QObject.connect(self.widget.btHome, qt.SIGNAL("clicked()"), self._homeTraj) qt.QObject.connect(self.widget.btDry, qt.SIGNAL("clicked()"), self._drySoakTraj) qt.QObject.connect(self.widget.btSoak, qt.SIGNAL("clicked()"), self._soakTraj) # qt.QObject.connect(self.widget.btMemoryClear, qt.SIGNAL('clicked()'), self._clearMemory) qt.QObject.connect( self.widget.btMemoryClear, qt.SIGNAL("clicked()"), self._ackSampleMemory ) qt.QObject.connect( self.widget.btToolOpen, qt.SIGNAL("clicked()"), self._openTool ) qt.QObject.connect( self.widget.btToolcal, qt.SIGNAL("clicked()"), self._toolcalTraj ) ### qt.QObject.connect( self.widget.btRegulationOn, qt.SIGNAL("clicked()"), self._regulationOn ) self.device = None self._pathRunning = None self._poweredOn = None self._regulationOn = None self._lid1State = False self._lid2State = False self._lid3State = False self._updateButtons()
def setupOptionsFrame(self): self.frame = qt.QFrame(self.scriptedEffect.optionsFrame()) qt.QFormLayout(self.frame) #Save space in the GUI self.frame.layout().setSpacing(0) self.frame.layout().setMargin(0) # self.helpLabel = qt.QLabel(self.frame) # self.helpLabel.setWordWrap(True) # #self.helpLabel.sizePolicy.setHorizontalPolicy(qt.QSizePolicy.Ignored) # #self.helpLabel.sizePolicy.setVerticalPolicy(qt.QSizePolicy.Ignored) # self.helpLabel.text = "Click on a lesion to start segmentation. \ # Depending on refinement settings, click again to refine globally and/or locally. Options may help deal \ # with cases such as segmenting individual lesions in a chain. \ # See <a href=\"https://www.slicer.org/wiki/Documentation/Nightly/Extensions/PETTumorSegmentation\">the documentation</a> for more information." # self.scriptedEffect.addOptionsWidget(self.helpLabel) # refinementBoxesFrame contains the options for how clicks are handled self.refinementBoxesFrame = qt.QFrame(self.frame) self.refinementBoxesFrame.setLayout(qt.QHBoxLayout()) self.refinementBoxesFrame.layout().setSpacing(0) self.refinementBoxesFrame.layout().setMargin(0) #default is global refinement (threshold refinement) self.noRefinementRadioButton = qt.QRadioButton( "Create new", self.refinementBoxesFrame) self.noRefinementRadioButton.setToolTip( "On click, always segment a new object.") self.globalRefinementRadioButton = qt.QRadioButton( "Global refinement", self.refinementBoxesFrame) self.globalRefinementRadioButton.setToolTip( "On click, refine globally (adjusting then entire boundary) if no center point for the label, otherwise segment a new object." ) self.localRefinementRadioButton = qt.QRadioButton( "Local refinement", self.refinementBoxesFrame) self.localRefinementRadioButton.setToolTip( "On click, refine locally (adjusting part of the boundary) if no center point for the label, otherwise segment a new object." ) self.globalRefinementRadioButton.setChecked(True) #radio button so only one can be applied self.refinementBoxesFrame.layout().addWidget( qt.QLabel("Interaction style: ", self.refinementBoxesFrame)) self.refinementBoxesFrame.layout().addWidget( self.noRefinementRadioButton) self.refinementBoxesFrame.layout().addWidget( self.globalRefinementRadioButton) self.refinementBoxesFrame.layout().addWidget( self.localRefinementRadioButton) self.refinementBoxesFrame.layout().addStretch(1) self.scriptedEffect.addOptionsWidget(self.refinementBoxesFrame) #options are hidden (collapsed) until requested self.optFrame = ctk.ctkCollapsibleGroupBox(self.frame) self.optFrame.setTitle("Options") self.optFrame.setLayout(qt.QVBoxLayout()) self.optFrame.visible = True self.optFrame.collapsed = True self.optFrame.setToolTip("Displays algorithm options.") #most useful options are kept on top: Splitting, Sealing, Assist Centering, Allow #Overwriting; to save vertical space, put 2 ina row, so subframes here with #horizontal layout are used #first row self.commonCheckBoxesFrame1 = qt.QFrame(self.optFrame) self.commonCheckBoxesFrame1.setLayout(qt.QHBoxLayout()) self.commonCheckBoxesFrame1.layout().setSpacing(0) self.commonCheckBoxesFrame1.layout().setMargin(0) self.optFrame.layout().addWidget(self.commonCheckBoxesFrame1) #top left self.splittingCheckBox = qt.QCheckBox("Splitting", self.commonCheckBoxesFrame1) self.splittingCheckBox.setToolTip( "Cut off adjacent objects to the target via watershed or local minimum. Useful for lymph node chains." ) self.splittingCheckBox.checked = False self.commonCheckBoxesFrame1.layout().addWidget(self.splittingCheckBox) #top right self.sealingCheckBox = qt.QCheckBox("Sealing", self.commonCheckBoxesFrame1) self.sealingCheckBox.setToolTip( "Close single-voxel gaps in the object or between the object and other objects, if above the threshold. Useful for lymph node chains." ) self.sealingCheckBox.checked = False self.commonCheckBoxesFrame1.layout().addWidget(self.sealingCheckBox) #second row self.commonCheckBoxesFrame2 = qt.QFrame(self.optFrame) self.commonCheckBoxesFrame2.setLayout(qt.QHBoxLayout()) self.commonCheckBoxesFrame2.layout().setSpacing(0) self.commonCheckBoxesFrame2.layout().setMargin(0) self.optFrame.layout().addWidget(self.commonCheckBoxesFrame2) #bottom left self.assistCenteringCheckBox = qt.QCheckBox( "Assist Centering", self.commonCheckBoxesFrame2) self.assistCenteringCheckBox.setToolTip( "Move the center to the highest voxel within 7 physical units, without being on or next to other object labels. Improves consistency." ) self.assistCenteringCheckBox.checked = True self.commonCheckBoxesFrame2.layout().addWidget( self.assistCenteringCheckBox) #bottom right self.allowOverwritingCheckBox = qt.QCheckBox( "Allow Overwriting", self.commonCheckBoxesFrame2) self.allowOverwritingCheckBox.setToolTip("Ignore other object labels.") self.allowOverwritingCheckBox.checked = False self.commonCheckBoxesFrame2.layout().addWidget( self.allowOverwritingCheckBox) self.scriptedEffect.addOptionsWidget(self.optFrame) #advanced options, for abnormal cases such as massive necrotic objects or #low-transition scans like phantoms #infrequently used, just keep vertical self.advFrame = ctk.ctkCollapsibleGroupBox(self.frame) self.advFrame.setTitle("Advanced") self.advFrame.setLayout(qt.QVBoxLayout()) self.advFrame.visible = True self.advFrame.collapsed = True self.advFrame.setToolTip( "Displays more advanced algorithm options. Do not use if you don't know what they mean." ) #top self.necroticRegionCheckBox = qt.QCheckBox("Necrotic Region", self.advFrame) self.necroticRegionCheckBox.setToolTip( "Prevents cutoff from low uptake. Use if placing a center inside a necrotic region." ) self.necroticRegionCheckBox.checked = False self.advFrame.layout().addWidget(self.necroticRegionCheckBox) #middle self.denoiseThresholdCheckBox = qt.QCheckBox("Denoise Threshold", self.advFrame) self.denoiseThresholdCheckBox.setToolTip( "Calculates threshold based on median-filtered image. Use only if scan is very noisey." ) self.denoiseThresholdCheckBox.checked = False self.advFrame.layout().addWidget(self.denoiseThresholdCheckBox) #bottom self.linearCostCheckBox = qt.QCheckBox("Linear Cost", self.advFrame) self.linearCostCheckBox.setToolTip( "Cost function below threshold is linear rather than based on region. Use only if little/no transition region in uptake." ) self.linearCostCheckBox.checked = False self.advFrame.layout().addWidget(self.linearCostCheckBox) self.optFrame.layout().addWidget(self.advFrame) #apply button kept at bottom of all options self.applyButton = qt.QPushButton("Apply", self.frame) self.optFrame.layout().addWidget(self.applyButton) self.applyButton.connect('clicked()', self.onApplyParameters) self.applyButton.setToolTip( "Redo last segmentation with the same center and refinement points with any changes in options." )
def setup(self, showPreview=False): """ main window is a frame with widgets from the app widget repacked into it along with slicer-specific extra widgets """ self.setWindowTitle('DICOM Browser') self.setLayout(qt.QVBoxLayout()) self.dicomBrowser.databaseDirectorySelectorVisible = False self.dicomBrowser.toolbarVisible = False self.dicomBrowser.sendActionVisible = True self.dicomBrowser.databaseDirectorySettingsKey = slicer.dicomDatabaseDirectorySettingsKey self.dicomBrowser.dicomTableManager().dynamicTableLayout = False horizontal = self.settings.setValue('DICOM/horizontalTables', 0) self.dicomBrowser.dicomTableManager( ).tableOrientation = qt.Qt.Horizontal if horizontal else qt.Qt.Vertical self.layout().addWidget(self.dicomBrowser) self.userFrame = qt.QWidget() self.preview = qt.QWidget() # # preview related column # self.previewLayout = qt.QVBoxLayout() if showPreview: self.previewLayout.addWidget(self.preview) else: self.preview.hide() # # action related column (interacting with slicer) # self.loadableTableFrame = qt.QWidget() self.loadableTableFrame.setMaximumHeight(200) self.loadableTableLayout = qt.QVBoxLayout(self.loadableTableFrame) self.layout().addWidget(self.loadableTableFrame) self.loadableTableLayout.addWidget(self.userFrame) self.userFrame.hide() self.loadableTable = DICOMLoadableTable(self.userFrame) self.loadableTable.itemChanged.connect(self.onLoadableTableItemChanged) # # button row for action column # self.actionButtonsFrame = qt.QWidget() self.actionButtonsFrame.setMaximumHeight(40) self.actionButtonsFrame.objectName = 'ActionButtonsFrame' self.layout().addWidget(self.actionButtonsFrame) self.actionButtonLayout = qt.QHBoxLayout() self.actionButtonsFrame.setLayout(self.actionButtonLayout) self.uncheckAllButton = qt.QPushButton('Uncheck All') self.actionButtonLayout.addWidget(self.uncheckAllButton) self.uncheckAllButton.connect('clicked()', self.uncheckAllLoadables) self.actionButtonLayout.addStretch(0.05) self.examineButton = qt.QPushButton('Examine') self.examineButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Fixed) self.actionButtonLayout.addWidget(self.examineButton) self.examineButton.enabled = False self.examineButton.connect('clicked()', self.examineForLoading) self.loadButton = qt.QPushButton('Load') self.loadButton.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Fixed) self.loadButton.toolTip = 'Load selected items into the scene' self.actionButtonLayout.addWidget(self.loadButton) self.loadButton.connect('clicked()', self.loadCheckedLoadables) self.actionButtonLayout.addStretch(0.05) self.advancedViewButton = qt.QCheckBox('Advanced') self.advancedViewButton.objectName = 'AdvancedViewCheckBox' self.actionButtonLayout.addWidget(self.advancedViewButton) self.advancedViewButton.checked = self.advancedView self.advancedViewButton.toggled.connect(self.onAdvancedViewButton) if self.advancedView: self.loadableTableFrame.visible = True else: self.loadableTableFrame.visible = False self.examineButton.visible = False self.uncheckAllButton.visible = False # # Series selection # self.dicomBrowser.dicomTableManager().connect( 'seriesSelectionChanged(QStringList)', self.onSeriesSelected) # # Loadable table widget (advanced) # DICOM Plugins selection widget is moved to module panel # self.loadableTableLayout.addWidget(self.loadableTable) self.updateButtonStates()
def buildInterface(self): vlayout = qt.QVBoxLayout(self) title = qt.QLabel("<B>Pixel Size Calibration<B>", self) title.setSizePolicy(qt.QSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Fixed)) vlayout.addWidget(title) self.calibFrame = qt.QFrame(self) self.calibFrame.setFrameShape(qt.QFrame.Box) self.calibFrame.setFrameShadow(qt.QFrame.Sunken) vlayout.addWidget(self.calibFrame) vlayout1 = qt.QVBoxLayout(self.calibFrame) vlayout1.setMargin(10) self.table = qttable.QTable(0, 3, self.calibFrame) self.table.setFocusPolicy(qt.QWidget.NoFocus) self.table.setSelectionMode(qttable.QTable.NoSelection) self.table.setSizePolicy(qt.QSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Minimum)) self.table.verticalHeader().hide() self.table.setLeftMargin(0) self.table.setReadOnly(True) header = self.table.horizontalHeader() header.setLabel(0, "Zoom") header.setLabel(1, "Y Size (nm)") header.setLabel(2, "Z Size (nm)") self.table.clearSelection(True) vlayout1.addWidget(self.table) vlayout1.addSpacing(10) f1 = qt.QFrame(self.calibFrame) f1.setFrameShape(qt.QFrame.HLine) f1.setFrameShadow(qt.QFrame.Sunken) vlayout1.addWidget(f1) vlayout1.addSpacing(10) self.saveButton = qt.QPushButton("Save Current Calibration", self.calibFrame) self.connect(self.saveButton, qt.SIGNAL("clicked()"), self.saveCalibration) vlayout1.addWidget(self.saveButton) vlayout1.addSpacing(10) f1 = qt.QFrame(self.calibFrame) f1.setFrameShape(qt.QFrame.HLine) f1.setFrameShadow(qt.QFrame.Sunken) vlayout1.addWidget(f1) vlayout1.addSpacing(10) hlayout1 = qt.QHBoxLayout(vlayout1) self.relYLabel = qt.QLabel("Y Move:", self.calibFrame) hlayout1.addWidget(self.relYLabel) self.relYText = qt.QLineEdit("0.1", self.calibFrame) hlayout1.addWidget(self.relYText) hlayout2 = qt.QHBoxLayout(vlayout1) self.relZLabel = qt.QLabel("Z Move:", self.calibFrame) hlayout2.addWidget(self.relZLabel) self.relZText = qt.QLineEdit("0.1", self.calibFrame) hlayout2.addWidget(self.relZText) vlayout1.addSpacing(5) self.calibButton = qt.QPushButton("Start New Calibration", self.calibFrame) self.connect(self.calibButton, qt.SIGNAL("clicked()"), self.calibrationAction) vlayout1.addWidget(self.calibButton) vlayout1.addStretch(1)
def setupOptionsFrame(self): self.methodSelectorComboBox = qt.QComboBox() self.methodSelectorComboBox.addItem("Grow from seeds", GROWCUT) self.methodSelectorComboBox.addItem("Fill between parallel slices", MORPHOLOGICAL_SLICE_INTERPOLATION) self.methodSelectorComboBox.setToolTip( """<html>Auto-complete methods:<ul style="margin: 0"> <li><b>Fill between slices:</b> Perform complete segmentation on selected slices using any editor effect. The complete segmentation will be created by interpolating segmentations on slices that were skipped.</li> <li><b>Expand segments:</b> Create segments using any editor effect: one segment inside each each region that should belong to a separate segment. Segments will be expanded to create a complete segmentation, taking into account the master volume content. Minimum two segments are required. (see http://insight-journal.org/browse/publication/977)</li> </ul></html>""") self.scriptedEffect.addLabeledOptionsWidget( "Method:", self.methodSelectorComboBox) self.autoUpdateCheckBox = qt.QCheckBox("Auto-update") self.autoUpdateCheckBox.setToolTip( "Auto-update results preview when input segments change.") self.autoUpdateCheckBox.setChecked(True) self.autoUpdateCheckBox.setEnabled(False) self.previewButton = qt.QPushButton("Initialize") self.previewButton.objectName = self.__class__.__name__ + 'Preview' self.previewButton.setToolTip("Preview complete segmentation") # qt.QSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding) # fails on some systems, therefore set the policies using separate method calls qSize = qt.QSizePolicy() qSize.setHorizontalPolicy(qt.QSizePolicy.Expanding) self.previewButton.setSizePolicy(qSize) previewFrame = qt.QHBoxLayout() previewFrame.addWidget(self.autoUpdateCheckBox) previewFrame.addWidget(self.previewButton) self.scriptedEffect.addLabeledOptionsWidget("Preview:", previewFrame) self.previewOpacitySlider = ctk.ctkSliderWidget() self.previewOpacitySlider.setToolTip( "Adjust visibility of results preview.") self.previewOpacitySlider.minimum = 0 self.previewOpacitySlider.maximum = 1.0 self.previewOpacitySlider.value = 0.0 self.previewOpacitySlider.singleStep = 0.05 self.previewOpacitySlider.pageStep = 0.1 self.previewOpacitySlider.spinBoxVisible = False displayFrame = qt.QHBoxLayout() displayFrame.addWidget(qt.QLabel("inputs")) displayFrame.addWidget(self.previewOpacitySlider) displayFrame.addWidget(qt.QLabel("results")) self.scriptedEffect.addLabeledOptionsWidget("Display:", displayFrame) self.cancelButton = qt.QPushButton("Cancel") self.cancelButton.objectName = self.__class__.__name__ + 'Cancel' self.cancelButton.setToolTip("Clear preview and cancel auto-complete") self.applyButton = qt.QPushButton("Apply") self.applyButton.objectName = self.__class__.__name__ + 'Apply' self.applyButton.setToolTip("Replace segments by previewed result") finishFrame = qt.QHBoxLayout() finishFrame.addWidget(self.cancelButton) finishFrame.addWidget(self.applyButton) self.scriptedEffect.addOptionsWidget(finishFrame) self.methodSelectorComboBox.connect("currentIndexChanged(int)", self.updateMRMLFromGUI) self.previewButton.connect('clicked()', self.onPreview) self.cancelButton.connect('clicked()', self.onCancel) self.applyButton.connect('clicked()', self.onApply) self.previewOpacitySlider.connect("valueChanged(double)", self.updateMRMLFromGUI) self.autoUpdateCheckBox.connect("stateChanged(int)", self.updateMRMLFromGUI)
def create(self): super().create() self.radiusFrame = qt.QFrame(self.frame) self.radiusFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.radiusFrame) self.widgets.append(self.radiusFrame) self.radiusLabel = qt.QLabel("Radius:", self.radiusFrame) self.radiusLabel.setToolTip( "Set the radius of the paint brush in millimeters") self.radiusFrame.layout().addWidget(self.radiusLabel) self.widgets.append(self.radiusLabel) self.radiusSpinBox = slicer.qMRMLSpinBox(self.radiusFrame) self.radiusSpinBox.objectName = 'SpinBox_Radius' self.radiusSpinBox.setToolTip( "Set the radius of the paint brush in millimeters") self.radiusSpinBox.quantity = "length" # QFlags not wrapped in python. Equivalent to Prefix | Suffix # See qMRMLSpinBox for more details. self.radiusSpinBox.unitAwareProperties = 0x01 | 0x02 self.radiusSpinBox.minimum = self.minimumRadius self.radiusSpinBox.maximum = self.maximumRadius self.radiusSpinBox.setMRMLScene(slicer.mrmlScene) from math import log, floor decimals = floor(log(self.minimumRadius, 10)) if decimals < 0: self.radiusSpinBox.decimals = -decimals + 2 self.radiusFrame.layout().addWidget(self.radiusSpinBox) self.widgets.append(self.radiusSpinBox) self.radiusUnitsToggle = qt.QPushButton("px:") self.radiusUnitsToggle.objectName = 'PushButton_RadiusUnitsToggle' self.radiusUnitsToggle.setToolTip( "Toggle radius quick set buttons between mm and label volume pixel size units" ) self.radiusUnitsToggle.setFixedWidth(35) self.radiusFrame.layout().addWidget(self.radiusUnitsToggle) self.radiusUnitsToggle.connect('clicked()', self.onRadiusUnitsToggle) self.radiusQuickies = {} quickies = ((2, self.onQuickie2Clicked), (3, self.onQuickie3Clicked), (4, self.onQuickie4Clicked), (5, self.onQuickie5Clicked), (10, self.onQuickie10Clicked), (20, self.onQuickie20Clicked)) for rad, callback in quickies: self.radiusQuickies[rad] = qt.QPushButton(str(rad)) self.radiusQuickies[ rad].objectName = f'PushButton_QuickRadius_{rad}' self.radiusFrame.layout().addWidget(self.radiusQuickies[rad]) self.radiusQuickies[rad].setFixedWidth(25) self.radiusQuickies[rad].connect('clicked()', callback) self.radiusQuickies[rad].setToolTip( "Set radius based on mm or label voxel size units depending on toggle value" ) self.radius = ctk.ctkDoubleSlider(self.frame) self.radius.objectName = 'DoubleSlider_Radius' self.radius.minimum = self.minimumRadius self.radius.maximum = self.maximumRadius self.radius.orientation = 1 self.radius.singleStep = self.minimumRadius self.frame.layout().addWidget(self.radius) self.widgets.append(self.radius) self.sphere = qt.QCheckBox("Sphere", self.frame) self.sphere.objectName = 'CheckBox_Sphere' self.sphere.setToolTip( "Use a 3D spherical brush rather than a 2D circular brush.") self.frame.layout().addWidget(self.sphere) self.widgets.append(self.sphere) self.smudge = qt.QCheckBox("Smudge", self.frame) self.smudge.objectName = 'CheckBox_Smudge' self.smudge.setToolTip( "Set the label number automatically by sampling the pixel location where the brush stroke starts." ) self.frame.layout().addWidget(self.smudge) self.widgets.append(self.smudge) self.pixelMode = qt.QCheckBox("Pixel Mode", self.frame) self.pixelMode.objectName = 'CheckBox_PixelMode' self.pixelMode.setToolTip( "Paint exactly the pixel under the cursor, ignoring the radius, threshold, and paint over." ) self.frame.layout().addWidget(self.pixelMode) self.widgets.append(self.pixelMode) HelpButton( self.frame, "Use this tool to paint with a round brush of the selected radius") self.connections.append( (self.sphere, 'clicked()', self.updateMRMLFromGUI)) self.connections.append( (self.smudge, 'clicked()', self.updateMRMLFromGUI)) self.connections.append( (self.pixelMode, 'clicked()', self.updateMRMLFromGUI)) self.connections.append( (self.radius, 'valueChanged(double)', self.onRadiusValueChanged)) self.connections.append((self.radiusSpinBox, 'valueChanged(double)', self.onRadiusSpinBoxChanged)) # Add vertical spacer self.frame.layout().addStretch(1)
def setupOptionsFrame(self): SegmentEditorThresholdEffect.setupOptionsFrame(self) # Hide threshold options self.applyButton.setHidden(True) self.useForPaintButton.setHidden(True) # Add diameter selector self.minimumDiameterSpinBox = slicer.qMRMLSpinBox() self.minimumDiameterSpinBox.setMRMLScene(slicer.mrmlScene) self.minimumDiameterSpinBox.quantity = "length" self.minimumDiameterSpinBox.value = 3.0 self.minimumDiameterSpinBox.singleStep = 0.5 self.minimumDiameterSpinBox.setToolTip( "Minimum diameter of the structure. Regions that are connected to the selected point by a bridge" " that this is thinner than this size will be excluded to prevent unwanted leaks through small holes." ) self.kernelSizePixel = qt.QLabel() self.kernelSizePixel.setToolTip( "Minimum diameter of the structure in pixels. Computed from the segment's spacing and the specified feature size." ) minimumDiameterFrame = qt.QHBoxLayout() minimumDiameterFrame.addWidget(self.minimumDiameterSpinBox) minimumDiameterFrame.addWidget(self.kernelSizePixel) self.minimumDiameterMmLabel = self.scriptedEffect.addLabeledOptionsWidget( "Minimum diameter:", minimumDiameterFrame) self.scriptedEffect.addOptionsWidget(minimumDiameterFrame) # Add algorithm options self.segmentationAlgorithmSelector = qt.QComboBox() self.segmentationAlgorithmSelector.addItem( SEGMENTATION_ALGORITHM_MASKING) self.segmentationAlgorithmSelector.addItem( SEGMENTATION_ALGORITHM_GROWCUT) self.segmentationAlgorithmSelector.addItem( SEGMENTATION_ALGORITHM_WATERSHED) self.scriptedEffect.addLabeledOptionsWidget( "Segmentation algorithm: ", self.segmentationAlgorithmSelector) # Add feature size selector self.featureSizeSpinBox = slicer.qMRMLSpinBox() self.featureSizeSpinBox.setMRMLScene(slicer.mrmlScene) self.featureSizeSpinBox.quantity = "length" self.featureSizeSpinBox.value = 3.0 self.featureSizeSpinBox.singleStep = 0.5 self.featureSizeSpinBox.setToolTip( "Spatial smoothness constraint used for WaterShed. Larger values result in smoother extracted surface." ) self.scriptedEffect.addLabeledOptionsWidget("Feature size: ", self.featureSizeSpinBox) # Add ROI options self.roiSelector = slicer.qMRMLNodeComboBox() self.roiSelector.nodeTypes = ['vtkMRMLAnnotationROINode'] self.roiSelector.noneEnabled = True self.roiSelector.setMRMLScene(slicer.mrmlScene) self.scriptedEffect.addLabeledOptionsWidget("ROI: ", self.roiSelector) # Connections self.minimumDiameterSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI) self.featureSizeSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI) self.segmentationAlgorithmSelector.connect("currentIndexChanged(int)", self.updateMRMLFromGUI)
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) self.logic = ProstateReportingLogic() self.uiLoader = qt.QUiLoader() self.patientName = None self.lesionList = None self.lesionListTags = [] # Instantiate and connect widgets ... # Load UI files self.scansWidget = self.loadUI('Scans') self.sectorMapWidget = self.loadUI('SectorMap') self.assessmentWidget = self.loadUI('Assessment') self.reportWidget = self.loadUI('Report') # Set up the sector relationships self.SectorMap = None self.initSectorMap() # # Volumes Area # scansCollapsibleButton = ctk.ctkCollapsibleButton() scansCollapsibleButton.text = "Patient Scans" self.layout.addWidget(scansCollapsibleButton) # Layout within the dummy collapsible button scansLayout = qt.QVBoxLayout(scansCollapsibleButton) # Patient name patientNameLayout = qt.QHBoxLayout() patientNameLayout.addWidget(qt.QLabel("Patient Name:")) self.patientNameLabel = qt.QLabel("") patientNameLayout.addWidget(self.patientNameLabel) scansLayout.addLayout(patientNameLayout) # Scans scansLayout.addWidget(self.scansWidget) self.t2VolumeSelector = self.logic.getChild(self.scansWidget, 't2VolumeSelector') self.t2VolumeSelector.setMRMLScene(slicer.mrmlScene) self.t2ScanDateLabel = self.logic.getChild(self.scansWidget, 't2ScanDateLabel') self.t1VolumeSelector = self.logic.getChild(self.scansWidget, 't1VolumeSelector') self.t1VolumeSelector.setMRMLScene(slicer.mrmlScene) self.t1ScanDateLabel = self.logic.getChild(self.scansWidget, 't1ScanDateLabel') self.dwiVolumeSelector = self.logic.getChild(self.scansWidget, 'dwiVolumeSelector') self.dwiVolumeSelector.setMRMLScene(slicer.mrmlScene) self.dwiScanDateLabel = self.logic.getChild(self.scansWidget, 'dwiScanDateLabel') self.adcVolumeSelector = self.logic.getChild(self.scansWidget, 'adcVolumeSelector') self.adcVolumeSelector.setMRMLScene(slicer.mrmlScene) self.adcScanDateLabel = self.logic.getChild(self.scansWidget, 'adcScanDateLabel') self.dceVolumeSelector = self.logic.getChild(self.scansWidget, 'dceVolumeSelector') self.dceVolumeSelector.setMRMLScene(slicer.mrmlScene) self.dceScanDateLabel = self.logic.getChild(self.scansWidget, 'dceScanDateLabel') # # Lesions Area # lesionsCollapsibleButton = ctk.ctkCollapsibleButton() lesionsCollapsibleButton.text = "Lesions" self.layout.addWidget(lesionsCollapsibleButton) # Layout within the dummy collapsible button lesionsLayout = qt.QVBoxLayout(lesionsCollapsibleButton) # Sector map sectorMapLabel = qt.QLabel() sectorMapLabel.setText("Prostate sector:") lesionsLayout.addWidget(sectorMapLabel) lesionsLayout.addWidget(self.sectorMapWidget) # Lesion target list if 0: self.targetListSelector = slicer.qMRMLNodeComboBox() self.targetListSelector.nodeTypes = ["vtkMRMLMarkupsFiducialNode"] self.targetListSelector.selectNodeUponCreation = True self.targetListSelector.addEnabled = True self.targetListSelector.removeEnabled = False self.targetListSelector.noneEnabled = False self.targetListSelector.showHidden = False self.targetListSelector.showChildNodeTypes = False self.targetListSelector.setMRMLScene(slicer.mrmlScene) self.targetListSelector.setToolTip( "Pick the list of target lesion fiducials.") lesionsLayout.addWidget(self.targetListSelector) # Add a lesion, will create a list if necessary. Will name it according # to sector selection self.addLesionButton = qt.QPushButton() self.addLesionButton.text = 'Add Lesion' lesionsLayout.addWidget(self.addLesionButton) # show the lesions in a table self.targetTableWidget = slicer.qSlicerSimpleMarkupsWidget() self.targetTableWidget.setMRMLScene(slicer.mrmlScene) lesionsLayout.addWidget(self.targetTableWidget) self.targetListSelector = self.logic.getChild( self.targetTableWidget, "MarkupsFiducialNodeComboBox") # hide the place button as want to rename fids when adding placeWidget = self.logic.getChild(self.targetTableWidget, "PlaceButton") placeWidget.hide() # # Assessment Area # assessmentCollapsibleButton = ctk.ctkCollapsibleButton() assessmentCollapsibleButton.text = "Assessment" self.layout.addWidget(assessmentCollapsibleButton) # Layout within the dummy collapsible button assessmentLayout = qt.QVBoxLayout(assessmentCollapsibleButton) assessmentLayout.addWidget(self.assessmentWidget) self.assessmentComboBox = self.logic.getChild(self.assessmentWidget, "assessmentComboBox") # # Report Area # self.reportButton = qt.QPushButton() self.reportButton.setText("Report") self.layout.addWidget(self.reportButton) # get the report widgets need to fill in self.reportPatientName = self.logic.getChild(self.reportWidget, "patientNameLabel") self.reportScans = self.logic.getChild(self.reportWidget, "patientScansTextEdit") self.reportLesions = self.logic.getChild(self.reportWidget, "patientLesionsTextEdit") self.reportAssessment = self.logic.getChild( self.reportWidget, "patientAssessmentTextEdit") self.reportNotes = self.logic.getChild(self.reportWidget, "patientNotesTextEdit") self.reportSave = self.logic.getChild(self.reportWidget, "savePushButton") self.reportCancel = self.logic.getChild(self.reportWidget, "cancelPushButton") # # Set up Connections # # Volumes self.t2VolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelectT2) self.t1VolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelectT1) self.dwiVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelectDWI) self.adcVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelectADC) self.dceVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelectDCE) # Lesions self.targetListSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelectTargets) # Sector map self.LRComboBox.connect("currentIndexChanged(int)", self.onSectorLRChanged) self.ZoneComboBox.connect("currentIndexChanged(int)", self.onSectorZoneChanged) self.GlandComboBox.connect("currentIndexChanged(int)", self.onSectorGlandChanged) self.APComboBox.connect("currentIndexChanged(int)", self.onSectorAPChanged) self.addLesionButton.connect('clicked(bool)', self.onAddLesion) # Report self.reportButton.connect('clicked(bool)', self.onReportButton) self.reportSave.connect('clicked(bool)', self.onReportSave) self.reportCancel.connect('clicked(bool)', self.onReportCancel) # Add vertical spacer self.layout.addStretch(1)
def __init__(self, parent, developerMode=False, widgetClass=None): VTKObservationMixin.__init__(self) # Set up main frame self.parent = parent self.parent.setLayout(qt.QHBoxLayout()) self.layout = self.parent.layout() self.layout.setMargin(0) self.layout.setSpacing(0) self.sliceletPanel = qt.QFrame(self.parent) self.sliceletPanelLayout = qt.QVBoxLayout(self.sliceletPanel) self.sliceletPanelLayout.setMargin(4) self.sliceletPanelLayout.setSpacing(0) self.layout.addWidget(self.sliceletPanel,1) #Set Advanced Parameters Collapsible Button self.parametersCollapsibleButton = ctk.ctkCollapsibleButton() self.parametersCollapsibleButton.text = "Set Advanced Segmentation Parameters" self.parametersCollapsibleButton.collapsed = True self.sliceletPanelLayout.addWidget(self.parametersCollapsibleButton) # Layout within the collapsible button self.parametersLayout = qt.QFormLayout(self.parametersCollapsibleButton) # Set Minimum Threshold of Percentage Increase to First Post-Contrast Image self.inputMinimumThreshold = qt.QLabel("Minimum Threshold of Increase", self.parametersCollapsibleButton) self.inputMinimumThreshold.setToolTip('Minimum Threshold of Percentage Increase (Pre- to First Post-contrast (Range: 10% to 150%)') self.inputSelectorMinimumThreshold = qt.QDoubleSpinBox(self.parametersCollapsibleButton) self.inputSelectorMinimumThreshold.setSuffix("%") self.inputSelectorMinimumThreshold.singleStep = (1) self.inputSelectorMinimumThreshold.minimum = (10) self.inputSelectorMinimumThreshold.maximum = (150) self.inputSelectorMinimumThreshold.value = (75) self.inputSelectorMinimumThreshold.setToolTip('Minimum Threshold of Percentage Increase (Pre- to First Post-contrast (Range: 10% to 150%)') self.parametersLayout.addRow(self.inputMinimumThreshold, self.inputSelectorMinimumThreshold) # Curve 1 Type Parameters (Slopes from First to Fourth Post-Contrast Images) self.inputCurve1 = qt.QLabel("Type 1 (Persistent) Curve Minimum Slope", self.parametersCollapsibleButton) self.inputCurve1.setToolTip('Minimum Slope of Delayed Curve to classify as Persistent (Range: 0.02 to 0.3)') self.inputSelectorCurve1 = qt.QDoubleSpinBox(self.parametersCollapsibleButton) self.inputSelectorCurve1.singleStep = (0.02) self.inputSelectorCurve1.minimum = (0.02) self.inputSelectorCurve1.maximum = (0.30) self.inputSelectorCurve1.value = (0.20) self.inputSelectorCurve1.setToolTip('Minimum Slope of Delayed Curve to classify as Persistent (Range: 0.02 to 0.3)') self.parametersLayout.addRow(self.inputCurve1, self.inputSelectorCurve1) # Curve 3 Type Parameters (Slopes from First to Fourth Post-Contrast Images) self.inputCurve3 = qt.QLabel("Type 3 (Washout) Curve Maximum Slope", self.parametersCollapsibleButton) self.inputCurve3.setToolTip('Maximum Slope of Delayed Curve to classify as Washout (Range: -0.02 to -0.3)') self.inputSelectorCurve3 = qt.QDoubleSpinBox(self.parametersCollapsibleButton) self.inputSelectorCurve3.singleStep = (0.02) self.inputSelectorCurve3.setPrefix("-") self.inputSelectorCurve3.minimum = (0.02) self.inputSelectorCurve3.maximum = (0.30) self.inputSelectorCurve3.value = (0.20) self.inputSelectorCurve3.setToolTip('Maximum Slope of Delayed Curve to classify as Washout (Range: -0.02 to -0.3)') self.parametersLayout.addRow(self.inputCurve3, self.inputSelectorCurve3) # Path input for dicom data to analyze self.inputPath = qt.QFileDialog() self.inputPath.setFileMode(qt.QFileDialog.Directory) self.sliceletPanelLayout.addWidget(self.inputPath) self.inputPath.connect('accepted()', self.createLogic) ############## self.layoutWidget = slicer.qMRMLLayoutWidget() self.layoutWidget.setMRMLScene(slicer.mrmlScene) self.layoutWidget.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutOneUp3DView) self.layout.addWidget(self.layoutWidget,2) if widgetClass: self.widget = widgetClass(self.parent) self.parent.show()
def setup(self): ScriptedLoadableModuleWidget.setup(self) self.logic = NeoGuidanceLogic() # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) self.layout.setContentsMargins(8, 8, 8, 8) # Layout within the collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) parametersFormLayout.setContentsMargins(8, 8, 8, 8) frame = qt.QWidget() layout = qt.QHBoxLayout(frame) layout.setContentsMargins(0, 0, 0, 0) layout.addStretch() layout.addWidget(qt.QLabel("Transforms")) layout.addStretch() parametersFormLayout.addRow(frame) # # 6DOF transform selector # self.sixDOFTransformSelector = slicer.qMRMLNodeComboBox() self.sixDOFTransformSelector.nodeTypes = ["vtkMRMLLinearTransformNode"] self.sixDOFTransformSelector.selectNodeUponCreation = True self.sixDOFTransformSelector.addEnabled = False self.sixDOFTransformSelector.removeEnabled = False self.sixDOFTransformSelector.noneEnabled = True self.sixDOFTransformSelector.showHidden = False self.sixDOFTransformSelector.showChildNodeTypes = False self.sixDOFTransformSelector.setMRMLScene(slicer.mrmlScene) self.sixDOFTransformSelector.setToolTip( "Pick the transform describing the 6DOF sensor.") parametersFormLayout.addRow("6DOF Transform: ", self.sixDOFTransformSelector) # # 6DOFModel to 6DOF transform selector # self.sixDOFModelTo6DOFTransformSelector = slicer.qMRMLNodeComboBox() self.sixDOFModelTo6DOFTransformSelector.nodeTypes = [ "vtkMRMLLinearTransformNode" ] self.sixDOFModelTo6DOFTransformSelector.selectNodeUponCreation = True self.sixDOFModelTo6DOFTransformSelector.addEnabled = False self.sixDOFModelTo6DOFTransformSelector.removeEnabled = False self.sixDOFModelTo6DOFTransformSelector.noneEnabled = True self.sixDOFModelTo6DOFTransformSelector.showHidden = False self.sixDOFModelTo6DOFTransformSelector.showChildNodeTypes = False self.sixDOFModelTo6DOFTransformSelector.setMRMLScene(slicer.mrmlScene) self.sixDOFModelTo6DOFTransformSelector.setToolTip( "Pick the transform describing the 6DOF model offset.") parametersFormLayout.addRow("6DOF Model Transform: ", self.sixDOFModelTo6DOFTransformSelector) # # 5DOF transform selector # self.fiveDOFTransformSelector = slicer.qMRMLNodeComboBox() self.fiveDOFTransformSelector.nodeTypes = [ "vtkMRMLLinearTransformNode" ] self.fiveDOFTransformSelector.selectNodeUponCreation = True self.fiveDOFTransformSelector.addEnabled = False self.fiveDOFTransformSelector.removeEnabled = False self.fiveDOFTransformSelector.noneEnabled = True self.fiveDOFTransformSelector.showHidden = False self.fiveDOFTransformSelector.showChildNodeTypes = False self.fiveDOFTransformSelector.setMRMLScene(slicer.mrmlScene) self.fiveDOFTransformSelector.setToolTip( "Pick the transform describing the 5DOF sensor.") parametersFormLayout.addRow("5DOF Transform: ", self.fiveDOFTransformSelector) # # 5DOFModel to 5DOFCalculated transform selector # self.fiveDOFModelTo5DOFCalculatedTransformSelector = slicer.qMRMLNodeComboBox( ) self.fiveDOFModelTo5DOFCalculatedTransformSelector.nodeTypes = [ "vtkMRMLLinearTransformNode" ] self.fiveDOFModelTo5DOFCalculatedTransformSelector.selectNodeUponCreation = True self.fiveDOFModelTo5DOFCalculatedTransformSelector.addEnabled = False self.fiveDOFModelTo5DOFCalculatedTransformSelector.removeEnabled = False self.fiveDOFModelTo5DOFCalculatedTransformSelector.noneEnabled = True self.fiveDOFModelTo5DOFCalculatedTransformSelector.showHidden = False self.fiveDOFModelTo5DOFCalculatedTransformSelector.showChildNodeTypes = False self.fiveDOFModelTo5DOFCalculatedTransformSelector.setMRMLScene( slicer.mrmlScene) self.fiveDOFModelTo5DOFCalculatedTransformSelector.setToolTip( "Pick the transform describing the 5DOF model offset.") parametersFormLayout.addRow( "5DOF Model Transform: ", self.fiveDOFModelTo5DOFCalculatedTransformSelector) # Separator frame = qt.QWidget() layout = qt.QHBoxLayout(frame) layout.setContentsMargins(0, 0, 0, 0) layout.addStretch() layout.addWidget(qt.QLabel("Images")) layout.addStretch() parametersFormLayout.addRow(frame) # # ICE volume selector # self.iceVolumeSelector = slicer.qMRMLNodeComboBox() self.iceVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] self.iceVolumeSelector.selectNodeUponCreation = True self.iceVolumeSelector.addEnabled = False self.iceVolumeSelector.removeEnabled = False self.iceVolumeSelector.noneEnabled = True self.iceVolumeSelector.showHidden = False self.iceVolumeSelector.showChildNodeTypes = False self.iceVolumeSelector.setMRMLScene(slicer.mrmlScene) self.iceVolumeSelector.setToolTip( "Pick the volume from the ICE transducer.") parametersFormLayout.addRow("ICE Image: ", self.iceVolumeSelector) # # mask volume selector # self.maskVolumeSelector = slicer.qMRMLNodeComboBox() self.maskVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] self.maskVolumeSelector.selectNodeUponCreation = True self.maskVolumeSelector.addEnabled = False self.maskVolumeSelector.removeEnabled = False self.maskVolumeSelector.noneEnabled = True self.maskVolumeSelector.showHidden = False self.maskVolumeSelector.showChildNodeTypes = False self.maskVolumeSelector.setMRMLScene(slicer.mrmlScene) self.maskVolumeSelector.setToolTip( "Pick the volume with the mask image for the ICE transducer.") parametersFormLayout.addRow("ICE Mask: ", self.maskVolumeSelector) # # TEE volume selector # self.teeVolumeSelector = slicer.qMRMLNodeComboBox() self.teeVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] self.teeVolumeSelector.selectNodeUponCreation = True self.teeVolumeSelector.addEnabled = False self.teeVolumeSelector.removeEnabled = False self.teeVolumeSelector.noneEnabled = True self.teeVolumeSelector.showHidden = False self.teeVolumeSelector.showChildNodeTypes = False self.teeVolumeSelector.setMRMLScene(slicer.mrmlScene) self.teeVolumeSelector.setToolTip( "Pick the volume from the TEE transducer.") parametersFormLayout.addRow("TEE Image: ", self.teeVolumeSelector) # # output volume selector # self.maskedICEVolumeSelector = slicer.qMRMLNodeComboBox() self.maskedICEVolumeSelector.nodeTypes = ["vtkMRMLScalarVolumeNode"] self.maskedICEVolumeSelector.selectNodeUponCreation = True self.maskedICEVolumeSelector.addEnabled = True self.maskedICEVolumeSelector.renameEnabled = True self.maskedICEVolumeSelector.removeEnabled = False self.maskedICEVolumeSelector.noneEnabled = True self.maskedICEVolumeSelector.showHidden = False self.maskedICEVolumeSelector.showChildNodeTypes = False self.maskedICEVolumeSelector.setMRMLScene(slicer.mrmlScene) self.maskedICEVolumeSelector.setToolTip( "Pick the volume for the masked output.") parametersFormLayout.addRow("Masked Output: ", self.maskedICEVolumeSelector) # Separator frame = qt.QWidget() layout = qt.QHBoxLayout(frame) layout.setContentsMargins(0, 0, 0, 0) layout.addStretch() layout.addWidget(qt.QLabel("Models")) layout.addStretch() parametersFormLayout.addRow(frame) # # nose model selector # self.noseModelSelector = slicer.qMRMLNodeComboBox() self.noseModelSelector.nodeTypes = ["vtkMRMLModelNode"] self.noseModelSelector.selectNodeUponCreation = True self.noseModelSelector.addEnabled = False self.noseModelSelector.renameEnabled = False self.noseModelSelector.removeEnabled = False self.noseModelSelector.noneEnabled = True self.noseModelSelector.showHidden = False self.noseModelSelector.showChildNodeTypes = False self.noseModelSelector.setMRMLScene(slicer.mrmlScene) self.noseModelSelector.setToolTip("Select the nose model.") parametersFormLayout.addRow("Nose Model: ", self.noseModelSelector) # # jaw model selector # self.jawModelSelector = slicer.qMRMLNodeComboBox() self.jawModelSelector.nodeTypes = ["vtkMRMLModelNode"] self.jawModelSelector.selectNodeUponCreation = True self.jawModelSelector.addEnabled = False self.jawModelSelector.renameEnabled = False self.jawModelSelector.removeEnabled = False self.jawModelSelector.noneEnabled = True self.jawModelSelector.showHidden = False self.jawModelSelector.showChildNodeTypes = False self.jawModelSelector.setMRMLScene(slicer.mrmlScene) self.jawModelSelector.setToolTip("Select the jaw model.") parametersFormLayout.addRow("Jaw Model: ", self.jawModelSelector) # # Actions Area # actionsCollapsibleButton = ctk.ctkCollapsibleButton() actionsCollapsibleButton.text = "Actions" self.layout.addWidget(actionsCollapsibleButton) # Layout within the collapsible button actionsFormLayout = qt.QFormLayout(actionsCollapsibleButton) actionsFormLayout.setContentsMargins(8, 8, 8, 8) # # Zero Button # self.zeroButton = qt.QPushButton("Zero") self.zeroButton.toolTip = "Calibrate the jaws to the home position." self.zeroButton.enabled = False frame = qt.QWidget() layout = qt.QHBoxLayout(frame) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(qt.QLabel("Zero Jaws:")) layout.addStretch() layout.addWidget(self.zeroButton) actionsFormLayout.addRow(frame) # # UI Buttons # self.minUIButton = qt.QPushButton("Minimal UI") self.minUIButton.toolTip = "Show minimal UI." self.normalUIButton = qt.QPushButton("Normal UI") self.normalUIButton.toolTip = "Show normal UI." frame = qt.QWidget() layout = qt.QHBoxLayout(frame) layout.setContentsMargins(0, 0, 0, 0) layout.addStretch() layout.addWidget(self.minUIButton) layout.addWidget(self.normalUIButton) actionsFormLayout.addRow(frame) # # On/Off Button # self.onOffButton = qt.QPushButton("Turn On") self.onOffButton.toolTip = "Toggle guidance." self.onOffButton.enabled = False self.onOffButton.icon = self._loadPixmap("off") frame = qt.QWidget() layout = qt.QHBoxLayout(frame) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(qt.QLabel("Guidance:")) layout.addStretch() layout.addWidget(self.onOffButton) actionsFormLayout.addRow(frame) # connections self.zeroButton.connect('clicked(bool)', self.onZeroButtonClicked) self.onOffButton.connect('clicked(bool)', self.onOffToggleButtonClicked) self.minUIButton.connect('clicked(bool)', self.onMinUIButtonClicked) self.normalUIButton.connect('clicked(bool)', self.onNormUIButtonClicked) self.sixDOFTransformSelector.connect( "currentNodeChanged(vtkMRMLNode*)", self.onSixDOFSelectorChanged) self.fiveDOFTransformSelector.connect( "currentNodeChanged(vtkMRMLNode*)", self.onFiveDOFSelectorChanged) self.maskVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onMaskSelectorChanged) self.teeVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onTEEVolumeSelectorChanged) self.iceVolumeSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onICESelectorChanged) self.maskedICEVolumeSelector.connect( "currentNodeChanged(vtkMRMLNode*)", self.onMaskedICEVolumeSelectorChanged) self.jawModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onJawModelSelectorChanged) self.noseModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onNoseModelSelectorChanged) self.sixDOFModelTo6DOFTransformSelector.connect( "currentNodeChanged(vtkMRMLNode*)", self.on6DOFModelTo6DOFSelectorChanged) self.fiveDOFModelTo5DOFCalculatedTransformSelector.connect( "currentNodeChanged(vtkMRMLNode*)", self.on5DOFModelTo5DOFCalculatedSelectorChanged) # Add vertical spacer self.layout.addStretch(1) # Refresh button state self.onSelect()
def _createSmall(self): """Make the internals of the widget to display in the Data Probe frame (lower left of slicer main window by default)""" # this method makes SliceView Annotation self.sliceAnnotations = DataProbeLib.SliceAnnotations() # goto module button self.goToModule = qt.QPushButton('->', self.frame) self.goToModule.setToolTip( 'Go to the DataProbe module for more information and options') self.frame.layout().addWidget(self.goToModule) self.goToModule.connect("clicked()", self.onGoToModule) # hide this for now - there's not much to see in the module itself self.goToModule.hide() # image view: To ensure the height of the checkbox matches the height of the # viewerFrame, it is added to a frame setting the layout and hard-coding the # content margins. # TODO: Revisit the approach and avoid hard-coding content margins self.showImageFrame = qt.QFrame(self.frame) self.frame.layout().addWidget(self.showImageFrame) self.showImageFrame.setLayout(qt.QHBoxLayout()) self.showImageFrame.layout().setContentsMargins(0, 3, 0, 3) self.showImageBox = qt.QCheckBox('Show Zoomed Slice', self.showImageFrame) self.showImageFrame.layout().addWidget(self.showImageBox) self.showImageBox.connect("toggled(bool)", self.onShowImage) self.showImageBox.setChecked(False) self.imageLabel = qt.QLabel() # qt.QSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding) # fails on some systems, therefore set the policies using separate method calls qSize = qt.QSizePolicy() qSize.setHorizontalPolicy(qt.QSizePolicy.Expanding) qSize.setVerticalPolicy(qt.QSizePolicy.Expanding) self.imageLabel.setSizePolicy(qSize) #self.imageLabel.setScaledContents(True) self.frame.layout().addWidget(self.imageLabel) self.onShowImage(False) # top row - things about the viewer itself self.viewerFrame = qt.QFrame(self.frame) self.viewerFrame.setLayout(qt.QHBoxLayout()) self.frame.layout().addWidget(self.viewerFrame) self.viewerColor = qt.QLabel(self.viewerFrame) self.viewerFrame.layout().addWidget(self.viewerColor) self.viewInfo = qt.QLabel() self.viewerFrame.layout().addWidget(self.viewInfo) self.viewerFrame.layout().addStretch(1) def _setFixedFontFamily(widget, family=None): if family is None: family = qt.QFontDatabase.systemFont( qt.QFontDatabase.FixedFont).family() font = widget.font font.setFamily(family) widget.font = font _setFixedFontFamily(self.viewInfo) # the grid - things about the layers # this method makes labels self.layerGrid = qt.QFrame(self.frame) layout = qt.QGridLayout() self.layerGrid.setLayout(layout) self.frame.layout().addWidget(self.layerGrid) layers = ('L', 'F', 'B') self.layerNames = {} self.layerIJKs = {} self.layerValues = {} for (row, layer) in enumerate(layers): col = 0 layout.addWidget(qt.QLabel(layer), row, col) col += 1 self.layerNames[layer] = qt.QLabel() layout.addWidget(self.layerNames[layer], row, col) col += 1 self.layerIJKs[layer] = qt.QLabel() layout.addWidget(self.layerIJKs[layer], row, col) col += 1 self.layerValues[layer] = qt.QLabel() layout.addWidget(self.layerValues[layer], row, col) layout.setColumnStretch(col, 100) _setFixedFontFamily(self.layerNames[layer]) _setFixedFontFamily(self.layerIJKs[layer]) _setFixedFontFamily(self.layerValues[layer]) # information collected about the current crosshair position # from displayable managers registered to the current view self.displayableManagerInfo = qt.QLabel() self.displayableManagerInfo.indent = 6 self.displayableManagerInfo.wordWrap = True self.frame.layout().addWidget(self.displayableManagerInfo) # only show if not empty self.displayableManagerInfo.hide() # goto module button self.goToModule = qt.QPushButton('->', self.frame) self.goToModule.setToolTip( 'Go to the DataProbe module for more information and options') self.frame.layout().addWidget(self.goToModule) self.goToModule.connect("clicked()", self.onGoToModule) # hide this for now - there's not much to see in the module itself self.goToModule.hide()
def __init__(self, *args): BlissWidget.__init__(self, *args) self.camera = None self.update_disabled = False self.__cameraName = None self.__zoomList = [1.5,2,2.5,3,3.5,4] self.__initZoom = 2 self.__fixWidth = -1 self.__fixHeight = -1 self.__swapRgb = True ####### PRINT ####### self.__printWidget = QubPrintPreview(self) self.__printWidget.resize(400,500) printer = qt.QPrinter() printer.setOutputToFile(1) printer.setOutputFileName('/tmp/print_file.ps') self.__printWidget.setPrinter(printer) self.__printWidget.update() self.__beamAction = None self.__scaleAction = None self.__chosenActions = {} self.__wholeActions = [] self.__measureDialog = None ####### PRINT ACTION ####### printAction = QubPrintPreviewAction(name="print",group="admin",withVectorMenu=True) printAction.previewConnect(self.__printWidget) self.__wholeActions.append(printAction) ####### SAVE IMAGE ####### self.__saveAction = QubSaveImageAction(parent=self, label='Save falcon image', name="save", group="admin") self.__saveAction.setConnectCallBack(self._save_dialog_new) self.__wholeActions.append(self.__saveAction) self.__defaultSavePath = '/tmp' ####### UPDATE ####### update = QubToggleAction(name="update",group="image",initState=True) self.connect(update,qt.PYSIGNAL("StateChanged"),self.__cameraUpdate) self.__wholeActions.append(update) ####### Start Camera ###### startCamera = QubToggleAction(name="startCamera", group="image", iconName = 'bright-cont', initState=True) self.connect(startCamera, qt.PYSIGNAL("StateChanged"), self.__cameraStart) self.__wholeActions.append(startCamera) ####### BRIGHTNESS/CONTRAST ####### self.__brightcount = QubOpenDialogAction(name="bright-cont", iconName = 'bright-cont', group="image") self.__brightcount.setDialog(QubBrightnessContrastDialog(self)) self.__wholeActions.append(self.__brightcount) ###### Grid TOOL ###### self.__gridToolAction = QubOpenDialogAction(parent=self, name='grid_tool', iconName='rectangle', label='Grid tool', group="Tools") #place="contextmenu") self.__gridDialog = GridDialog(self, "Grid Dialog", flags = qt.Qt.WStyle_StaysOnTop) self.__gridToolAction.setConnectCallBack(self._grid_dialog_connect_hdlr) self.__wholeActions.append(self.__gridToolAction) self.__previous_pos_dict = {} self.__beamWidth = 0 self.__beamHeight = 0 ####### BEAM ACTION ####### self.__beamAction = QubBeamAction(name="beam", group="Tools") self.__wholeActions.append(self.__beamAction) self.connect(self.__beamAction,qt.PYSIGNAL("BeamSelected"), self.beamSelection) ####### SCALE ####### self.__scaleAction = QubScaleAction(name='scale',group='Tools') self.__wholeActions.append(self.__scaleAction) self.__wholeActions.extend(self.__creatStdActions()) ####### ACTION INFO ####### actionInfo = QubInfoAction(name="actionInfo", group="image",place="statusbar") self.__wholeActions.append(actionInfo) ####### CHANGE FOREGROUND COLOR ####### self.__fcoloraction = QubForegroundColorAction(name="color", group="image") self.__wholeActions.append(self.__fcoloraction) ####### MEASURE ####### self.__measureAction = QubOpenDialogAction(parent=self, name='measure', iconName='measure', label='Measure', group="Tools") self.__measureAction.setConnectCallBack(self._measure_dialog_new) self.__wholeActions.append(self.__measureAction) # ###### POSITION TOOL ###### # self.__posToolAction = QubOpenDialogAction(parent=self, name='pos_tool', # iconName='circle', label='Position tool', # group="Tools") # self.__posToolAction.setConnectCallBack(self._line_dialog_new) # self.__wholeActions.append(self.__posToolAction) ####### ZOOM LIST ####### zoomActionList = QubZoomListAction(place = "toolbar", initZoom = 1,zoomValList = [0.1,0.25,0.5,0.75,1,1.5,2], show = 1,group = "zoom") self.__wholeActions.append(zoomActionList) ####### ZOOM Action ####### self.__zoomFitOrFill = QubZoomAction(place = "toolbar",group = "zoom") self.__wholeActions.append(self.__zoomFitOrFill) ####### LINK ZOOM ACTION ####### self.__zoomFitOrFill.setList(zoomActionList) zoomActionList.setActionZoomMode(self.__zoomFitOrFill) ####### ZOOM WINDOW ####### self.__zoomAction = QubZoomRectangle(label='Zoom Crop',place="toolbar", show=1, group="zoom") self.connect(self.__zoomAction,qt.PYSIGNAL("Actif"),self.__hide_show_zoom) self.__wholeActions.append(self.__zoomAction) self.__splitter = qt.QSplitter(qt.Qt.Horizontal,self) self.__splitter.show() self.__mainVideo = QubPixmapDisplayView(self.__splitter) self.__mainVideo.show() self.__mainVideo.setScrollbarMode('Auto') self.__mainPlug = _MainVideoPlug(self.__mainVideo,self.__zoomAction) actions = self.__creatStdActions() ####### ZOOM LIST ####### self.__zoomActionList = QubZoomListAction(place = "toolbar",keepROI = True, initZoom = self.__initZoom,zoomValList = self.__zoomList, show = 1,group = "zoom") actions.insert(0,self.__zoomActionList) ####### ZOOM Action ####### zoomFitOrFill = QubZoomAction(place = "toolbar",keepROI = True,group = "zoom") zoomFitOrFill.setList(self.__zoomActionList) self.__zoomActionList.setActionZoomMode(zoomFitOrFill) actions.append(zoomFitOrFill) self.__zoomVideo = QubPixmapDisplayView(self.__splitter,None,actions) self.__zoomVideo.hide() self.__zoomPlug = _ZoomPlug(self.__zoomVideo) self.__zoomPlug.zoom().setZoom(2,2) self.__cbk = _rectangleZoom(self.__zoomAction,self.__zoomPlug) layout = qt.QHBoxLayout(self,0,0,"layout") layout.addWidget(self.__splitter) self.__image2Pixmap = QubImage2Pixmap() self.__image2Pixmap.plug(self.__mainPlug) self.__zoomPlug.setPoller(self.__image2Pixmap) self.__jpegDecompress = QubStdData2Image() self.__jpegDecompress.setSwapRGB(True) self.__jpeg2image = None ####### PROPERTY ####### self.addProperty('camera','string','') self.addProperty('zoom list','string',','.join([str(x) for x in self.__zoomList])) self.addProperty('init zoom','integer',self.__initZoom) self.addProperty('swap rgb','boolean',True) self.addProperty('fix : width','integer',-1) self.addProperty('fix : height','integer',-1) self.addProperty('action : print','boolean',True) self.addProperty('action : save image','boolean',True) self.addProperty('action : update','boolean',True) self.addProperty('action : startCamera','boolean',True) self.addProperty('action : brightness contrast','boolean',True) self.addProperty('action : beam','boolean',True) self.addProperty('action : scale','boolean',True) self.addProperty('action : change foreground color','boolean',True) self.addProperty('action : measure','boolean',True) self.addProperty('action : measure (place)', 'combo', ('toolbar','contextmenu'),'toolbar') self.addProperty('action : zoom window','boolean',True) self.addProperty('action : zoom fit or fill','boolean',True) self.addProperty('action : zoom list','boolean',True) self.addProperty('action : x,y coordinates','boolean',True) self.addProperty('action : default color','combo',('black','red','green'),'black') self.addProperty('action : save image (place)',"combo",('toolbar','contextmenu'),'toolbar') self.addProperty('action : save image (default path)',"string",'/tmp') self.addProperty('action : save image (show always configure)',"boolean",True) self.addProperty("diffractometer", "string", "") self.diffractometerHwobj = None ####### SIGNAL ####### self.defineSignal("BeamPositionChanged", ()) ####### SLOT ####### self.defineSlot("changeBeamPosition", ()) self.defineSlot("changePixelScale",()) self.defineSlot('getView',()) self.defineSlot('getImage',()) ####### LINK VIEW AND SUB VIEW ####### mainView = self.__mainVideo.view() zoomView = self.__zoomVideo.view() mainView.addEventMgrLink(zoomView, mainView.canvas(),zoomView.canvas(), mainView.matrix(),zoomView.matrix()) self.imageReceivedConnected = None
def setup(self): # Message suggesting using Segment Editor self.createSegmentEditorMessage() # # Editor Volumes # # only if showing volumes if self.showVolumesFrame: self.volumes = ctk.ctkCollapsibleButton(self.parent) self.volumes.objectName = 'VolumeCollapsibleButton' self.volumes.setLayout(qt.QVBoxLayout()) self.volumes.setText("Create and Select Label Maps") self.layout.addWidget(self.volumes) else: self.volumes = None # create the helper box - note this isn't a Qt widget # but a helper class that creates Qt widgets in the given parent if self.showVolumesFrame: self.helper = EditorLib.HelperBox(self.volumes) else: self.helper = None # # Tool Frame # # (we already have self.parent for the parent widget, and self.layout for the layout) # create the frames for the EditColor, toolsOptionsFrame and EditBox # create collapsible button for entire "edit label maps" section self.editLabelMapsFrame = ctk.ctkCollapsibleButton(self.parent) self.editLabelMapsFrame.objectName = 'EditLabelMapsFrame' self.editLabelMapsFrame.setLayout(qt.QVBoxLayout()) self.editLabelMapsFrame.setText("Edit Selected Label Map") self.layout.addWidget(self.editLabelMapsFrame) self.editLabelMapsFrame.collapsed = True # create frame holding both the effect options and edit box: self.effectsToolsFrame = qt.QFrame(self.editLabelMapsFrame) self.effectsToolsFrame.objectName = 'EffectsToolsFrame' self.effectsToolsFrame.setLayout(qt.QHBoxLayout()) self.editLabelMapsFrame.layout().addStretch(1) self.editLabelMapsFrame.layout().addWidget(self.effectsToolsFrame) # create frame for effect options self.createEffectOptionsFrame() # create and add frame for EditBox self.createEditBox() # create and add EditColor directly to "edit label map" section self.toolsColor = EditorLib.EditColor(self.editLabelMapsFrame) # put the tool options below the color selector self.editLabelMapsFrame.layout().addWidget(self.effectOptionsFrame) if self.helper: # add a callback to collapse/open the frame based on the validity of the label volume self.helper.mergeValidCommand = self.updateLabelFrame # add a callback to reset the tool when a new volume is selected self.helper.selectCommand = self.toolsBox.defaultEffect # Add spacer to layout self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # input warp selector # inputFrame = qt.QFrame() inputFrame.setLayout(qt.QHBoxLayout()) self.inputSelector = slicer.qMRMLNodeComboBox() self.inputSelector.nodeTypes = ["vtkMRMLGridTransformNode"] self.inputSelector.selectNodeUponCreation = False self.inputSelector.addEnabled = True self.inputSelector.removeEnabled = False self.inputSelector.noneEnabled = True self.inputSelector.showHidden = False self.inputSelector.showChildNodeTypes = False self.inputSelector.setMRMLScene(slicer.mrmlScene) self.inputSelector.setToolTip("Pick the input to the algorithm.") inputFrame.layout().addWidget(qt.QLabel('Input Transform: ')) inputFrame.layout().addWidget(self.inputSelector) self.layout.addWidget(inputFrame) # # Grid reference # emptyTransformCollapsibleButton = ctk.ctkCollapsibleButton() emptyTransformCollapsibleButton.text = "Grid Reference" self.layout.addWidget(emptyTransformCollapsibleButton) # Layout within the dummy collapsible button emptyTransformFormLayout = qt.QFormLayout( emptyTransformCollapsibleButton) self.transformSizeSelect = ctk.ctkCoordinatesWidget() self.transformSizeSelect.coordinates = '193,229,193' self.transformSizeSelect.setDecimals(0) emptyTransformFormLayout.addRow("Size", self.transformSizeSelect) self.transformOriginSelect = ctk.ctkCoordinatesWidget() self.transformOriginSelect.coordinates = '-96.0, -132.0, -78.0' emptyTransformFormLayout.addRow("Origin", self.transformOriginSelect) self.transformSpacingSelect = ctk.ctkCoordinatesWidget() self.transformSpacingSelect.coordinates = '1.0, 1.0, 1.0' emptyTransformFormLayout.addRow("Spacing", self.transformSpacingSelect) # # Operations # operationsCollapsibleButton = ctk.ctkCollapsibleButton() operationsCollapsibleButton.text = "Operations" self.layout.addWidget(operationsCollapsibleButton) # Layout within the dummy collapsible button operationsFormLayout = qt.QFormLayout(operationsCollapsibleButton) # Empty Button self.emptyButton = qt.QPushButton("Empty Transform") self.emptyButton.enabled = False operationsFormLayout.addRow(self.emptyButton) # Flatten Button & opts flattenFrame = qt.QFrame() flattenFrame.setLayout(qt.QHBoxLayout()) self.includeFirstLayerCB = qt.QCheckBox('Include First Layer') self.includeFirstLayerCB.toolTip = "If selected all the layers of the composite transform will be flattened taking the first grid as reference. If not, the layers starting from the second one will be flattened and append to the first one. In this case the reference grid is used to flatten the transform" flattenFrame.layout().addWidget(self.includeFirstLayerCB) self.flattenButton = qt.QPushButton("Flatten Transform") self.flattenButton.enabled = False flattenFrame.layout().addWidget(self.flattenButton, 2) operationsFormLayout.addRow(flattenFrame) # Remove last layer self.removeLastLayerButton = qt.QPushButton("Remove Last Layer") self.removeLastLayerButton.enabled = False operationsFormLayout.addRow(self.removeLastLayerButton) # connections self.emptyButton.connect('clicked(bool)', self.onEmptyButton) self.flattenButton.connect('clicked(bool)', self.onFlattenButton) self.removeLastLayerButton.connect('clicked(bool)', self.onRemoveLastLayerButton) self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelect()
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 setupOptionsFrame(self): self.methodSelectorComboBox = qt.QComboBox() self.methodSelectorComboBox.addItem("Median", MEDIAN) self.methodSelectorComboBox.addItem("Opening (remove extrusions)", MORPHOLOGICAL_OPENING) self.methodSelectorComboBox.addItem("Closing (fill holes)", MORPHOLOGICAL_CLOSING) self.methodSelectorComboBox.addItem("Gaussian", GAUSSIAN) self.methodSelectorComboBox.addItem("Joint smoothing", JOINT_TAUBIN) self.scriptedEffect.addLabeledOptionsWidget( "Smoothing method:", self.methodSelectorComboBox) self.kernelSizeMmSpinBox = slicer.qMRMLSpinBox() self.kernelSizeMmSpinBox.setMRMLScene(slicer.mrmlScene) self.kernelSizeMmSpinBox.setToolTip( "Diameter of the neighborhood that will be considered around each voxel. Higher value makes smoothing stronger (more details are suppressed)." ) self.kernelSizeMmSpinBox.quantity = "length" self.kernelSizeMmSpinBox.minimum = 0.0 self.kernelSizeMmSpinBox.value = 3.0 self.kernelSizeMmSpinBox.singleStep = 1.0 self.kernelSizePixel = qt.QLabel() self.kernelSizePixel.setToolTip( "Diameter of the neighborhood in pixels. Computed from the segment's spacing and the specified kernel size." ) kernelSizeFrame = qt.QHBoxLayout() kernelSizeFrame.addWidget(self.kernelSizeMmSpinBox) kernelSizeFrame.addWidget(self.kernelSizePixel) self.kernelSizeMmLabel = self.scriptedEffect.addLabeledOptionsWidget( "Kernel size:", kernelSizeFrame) self.gaussianStandardDeviationMmSpinBox = slicer.qMRMLSpinBox() self.gaussianStandardDeviationMmSpinBox.setMRMLScene(slicer.mrmlScene) self.gaussianStandardDeviationMmSpinBox.setToolTip( "Standard deviation of the Gaussian smoothing filter coefficients. Higher value makes smoothing stronger (more details are suppressed)." ) self.gaussianStandardDeviationMmSpinBox.quantity = "length" self.gaussianStandardDeviationMmSpinBox.value = 3.0 self.gaussianStandardDeviationMmSpinBox.singleStep = 1.0 self.gaussianStandardDeviationMmLabel = self.scriptedEffect.addLabeledOptionsWidget( "Standard deviation:", self.gaussianStandardDeviationMmSpinBox) self.jointTaubinSmoothingFactorSlider = ctk.ctkSliderWidget() self.jointTaubinSmoothingFactorSlider.setToolTip( "Higher value means stronger smoothing.") self.jointTaubinSmoothingFactorSlider.minimum = 0.01 self.jointTaubinSmoothingFactorSlider.maximum = 1.0 self.jointTaubinSmoothingFactorSlider.value = 0.5 self.jointTaubinSmoothingFactorSlider.singleStep = 0.01 self.jointTaubinSmoothingFactorSlider.pageStep = 0.1 self.jointTaubinSmoothingFactorLabel = self.scriptedEffect.addLabeledOptionsWidget( "Smoothing factor:", self.jointTaubinSmoothingFactorSlider) self.applyButton = qt.QPushButton("Apply") self.applyButton.objectName = self.__class__.__name__ + 'Apply' self.applyButton.setToolTip("Apply smoothing to selected segment") self.scriptedEffect.addOptionsWidget(self.applyButton) self.methodSelectorComboBox.connect("currentIndexChanged(int)", self.updateMRMLFromGUI) self.kernelSizeMmSpinBox.connect("valueChanged(double)", self.updateMRMLFromGUI) self.gaussianStandardDeviationMmSpinBox.connect( "valueChanged(double)", self.updateMRMLFromGUI) self.jointTaubinSmoothingFactorSlider.connect("valueChanged(double)", self.updateMRMLFromGUI) self.applyButton.connect('clicked()', self.onApply)
def createHLayout(elements): rowLayout = qt.QHBoxLayout() for element in elements: rowLayout.addWidget(element) return rowLayout
def __init__(self, logic): super(VisualizationWidget, self).__init__() self.rockCount = 0 self.rocking = False self.rockTimer = None self.flickerTimer = None self.logic = logic self.revealCursor = None self.volumes = ( "Fixed", "Moving", "Transformed", ) self.layoutOptions = ( "Axial", "Coronal", "Sagittal", "Axi/Sag/Cor", ) self.layoutOption = 'Axi/Sag/Cor' self.volumeDisplayCheckboxes = {} # mimic the structure of the LandmarksWidget for visual # consistency (it needs sub widget so it can delete and refresh the internals) self.widget = qt.QWidget() self.layout = qt.QFormLayout(self.widget) self.boxHolder = qt.QWidget() self.boxHolder.setLayout(qt.QVBoxLayout()) self.layout.addRow(self.boxHolder) self.groupBox = qt.QGroupBox("Visualization") self.groupBoxLayout = qt.QFormLayout(self.groupBox) self.boxHolder.layout().addWidget(self.groupBox) # # layout selection # layoutHolder = qt.QWidget() layout = qt.QHBoxLayout() layoutHolder.setLayout(layout) for layoutOption in self.layoutOptions: layoutButton = qt.QPushButton(layoutOption) layoutButton.connect('clicked()', lambda lo=layoutOption: self.selectLayout(lo)) layout.addWidget(layoutButton) self.groupBoxLayout.addRow("Layout", layoutHolder) # # Volume display selection # checkboxHolder = qt.QWidget() layout = qt.QHBoxLayout() checkboxHolder.setLayout(layout) for volume in self.volumes: checkBox = qt.QCheckBox() checkBox.text = volume checkBox.checked = True checkBox.connect('toggled(bool)', self.updateVisualization) layout.addWidget(checkBox) self.volumeDisplayCheckboxes[volume] = checkBox checkBox = qt.QCheckBox() checkBox.text = "RevealCursor" checkBox.checked = False checkBox.connect('toggled(bool)', self.revealToggled) layout.addWidget(checkBox) self.groupBoxLayout.addRow("Display", checkboxHolder) # # fade slider # fadeHolder = qt.QWidget() fadeLayout = qt.QHBoxLayout() fadeHolder.setLayout(fadeLayout) self.fadeSlider = ctk.ctkSliderWidget() self.fadeSlider.minimum = 0 self.fadeSlider.maximum = 1.0 self.fadeSlider.value = 0.5 self.fadeSlider.singleStep = 0.05 self.fadeSlider.connect('valueChanged(double)', self.onFadeChanged) fadeLayout.addWidget(self.fadeSlider) # # Rock and Flicker # animaHolder = qt.QWidget() animaLayout = qt.QVBoxLayout() animaHolder.setLayout(animaLayout) fadeLayout.addWidget(animaHolder) # Rock checkBox = qt.QCheckBox() checkBox.text = "Rock" checkBox.checked = False checkBox.connect('toggled(bool)', self.onRockToggled) animaLayout.addWidget(checkBox) # Flicker checkBox = qt.QCheckBox() checkBox.text = "Flicker" checkBox.checked = False checkBox.connect('toggled(bool)', self.onFlickerToggled) animaLayout.addWidget(checkBox) self.groupBoxLayout.addRow("Fade", fadeHolder) # # zoom control # zoomHolder = qt.QWidget() layout = qt.QHBoxLayout() zoomHolder.setLayout(layout) zooms = { "+": 0.7, "-": 1.3, "Fit": "Fit", } for zoomLabel, zoomFactor in zooms.items(): zoomButton = qt.QPushButton(zoomLabel) zoomButton.connect('clicked()', lambda zf=zoomFactor: self.onZoom(zf)) layout.addWidget(zoomButton) self.groupBoxLayout.addRow("Zoom", zoomHolder)
def setupOptionsFrame(self): self.interpolationRadioButtons = [] # Fiducial Placement widget self.fiducialPlacementToggle = slicer.qSlicerMarkupsPlaceWidget() self.fiducialPlacementToggle.setMRMLScene(slicer.mrmlScene) self.fiducialPlacementToggle.placeMultipleMarkups = self.fiducialPlacementToggle.ForcePlaceMultipleMarkups self.fiducialPlacementToggle.buttonsVisible = False self.fiducialPlacementToggle.show() self.fiducialPlacementToggle.placeButton().show() self.fiducialPlacementToggle.deleteButton().show() # Edit surface button self.editButton = qt.QPushButton("Edit") self.editButton.objectName = self.__class__.__name__ + 'Edit' self.editButton.setToolTip( "Edit the previously placed group of fiducials.") fiducialActionLayout = qt.QHBoxLayout() fiducialActionLayout.addWidget(self.fiducialPlacementToggle) fiducialActionLayout.addWidget(self.editButton) self.scriptedEffect.addLabeledOptionsWidget("Fiducial Placement: ", fiducialActionLayout) # Radius spinbox self.radiusSpinBox = slicer.qMRMLSpinBox() self.radiusSpinBox.value = self.logic.radius self.radiusSpinBox.quantity = 'length' self.radiusSpinBox.unitAwareProperties = slicer.qMRMLSpinBox.MaximumValue | slicer.qMRMLSpinBox.Precision | slicer.qMRMLSpinBox.Prefix | slicer.qMRMLSpinBox.Suffix self.scriptedEffect.addLabeledOptionsWidget("Radius: ", self.radiusSpinBox) # Interpolation buttons self.piecewiseLinearButton = qt.QRadioButton("Piecewise linear") self.interpolationRadioButtons.append(self.piecewiseLinearButton) self.buttonToInterpolationTypeMap[ self.piecewiseLinearButton] = "LINEAR" self.cardinalSplineButton = qt.QRadioButton("Cardinal spline") self.interpolationRadioButtons.append(self.cardinalSplineButton) self.buttonToInterpolationTypeMap[ self.cardinalSplineButton] = "CARDINAL_SPLINE" self.kochanekSplineButton = qt.QRadioButton("Kochanek spline") self.interpolationRadioButtons.append(self.kochanekSplineButton) self.buttonToInterpolationTypeMap[ self.kochanekSplineButton] = "KOCHANEK_SPLINE" self.globalPolynomialButton = qt.QRadioButton("Global polynomial") self.interpolationRadioButtons.append(self.globalPolynomialButton) self.buttonToInterpolationTypeMap[ self.globalPolynomialButton] = "GLOBAL_POLYNOMIAL" self.movingPolynomialButton = qt.QRadioButton("Moving polynomial") self.interpolationRadioButtons.append(self.movingPolynomialButton) self.buttonToInterpolationTypeMap[ self.movingPolynomialButton] = "MOVING_POLYNOMIAL" # Segments per point spinbox self.numberOfLineSegmentsSpinBox = qt.QSpinBox() self.numberOfLineSegmentsSpinBox.value = 15 # To keep GUI simple, we do not show numberOfLineSegmentsSpinBox. # Default value should work for most cases and modules can programmatically change this value, if needed. # If user feedback confirms that this parameter must be exposed then the next line can be uncommented. # self.scriptedEffect.addLabeledOptionsWidget("Segments between points: ", self.numberOfLineSegmentsSpinBox) # Interpolation buttons layout interpolationLayout = qt.QGridLayout() interpolationLayout.addWidget(self.piecewiseLinearButton, 0, 0) interpolationLayout.addWidget(self.cardinalSplineButton, 1, 0) interpolationLayout.addWidget(self.kochanekSplineButton, 0, 1) interpolationLayout.addWidget(self.globalPolynomialButton, 1, 1) interpolationLayout.addWidget(self.movingPolynomialButton, 0, 2) self.scriptedEffect.addLabeledOptionsWidget("Interpolation:", interpolationLayout) # Apply button self.applyButton = qt.QPushButton("Apply") self.applyButton.objectName = self.__class__.__name__ + 'Apply' self.applyButton.setToolTip("Generate tube from markup fiducials.") self.scriptedEffect.addOptionsWidget(self.applyButton) # Cancel button self.cancelButton = qt.QPushButton("Cancel") self.cancelButton.objectName = self.__class__.__name__ + 'Cancel' self.cancelButton.setToolTip("Clear fiducials and remove from scene.") # Finish action buttons finishAction = qt.QHBoxLayout() finishAction.addWidget(self.cancelButton) finishAction.addWidget(self.applyButton) self.scriptedEffect.addOptionsWidget(finishAction) # Connections for button in self.interpolationRadioButtons: button.connect('toggled(bool)', lambda toggle, widget=self. buttonToInterpolationTypeMap[button]: self. onInterpolationSelectionChanged(widget, toggle)) self.applyButton.connect('clicked()', self.onApply) self.cancelButton.connect('clicked()', self.onCancel) self.editButton.connect('clicked()', self.onEdit) self.fiducialPlacementToggle.placeButton().clicked.connect( self.onFiducialPlacementToggleChanged) self.radiusSpinBox.connect('valueChanged(double)', self.onRadiusChanged) self.numberOfLineSegmentsSpinBox.connect( 'valueChanged(int)', self.onNumberOfLineSegmentsChanged)
def __init__(self, parent=None, name="data_collect", selection_changed=None): qt.QWidget.__init__(self, parent, name) # Internal members self.collecting = False self.centring_method = 0 self.queue_hwobj = None self.queue_model_hwobj = None self.beamline_setup_hwobj = None self.sample_centring_result = gevent.event.AsyncResult() # HW-Object set by TreeBrick self.sample_changer_hwobj = None self.plate_manipulator_hwobj = None self.hl_motor_hwobj = None self.tree_brick = self.parent() self.sample_item_list = [] self.collect_tree_task = None self.user_stopped = False self.plate_sample_to_mount = None # Callbacks TODO:Document better self.selection_changed_cb = None self.collect_stop_cb = None #self.clear_centred_positions_cb = None self.run_cb = None # Layout self.setCaption("Data collect") self.confirm_dialog = ConfirmDialog(self, 'Confirm Dialog') self.confirm_dialog.setModal(True) self.pin_pixmap = Icons.load("sample_axis.png") self.task_pixmap = Icons.load("task.png") self.play_pixmap = Icons.load("VCRPlay.png") self.stop_pixmap = Icons.load("Stop.png") self.up_pixmap = Icons.load("Up2.png") self.down_pixmap = Icons.load("Down2.png") self.delete_pixmap = Icons.load("bin_small.png") self.ispyb_pixmap = Icons.load("SampleChanger2.png") self.caution_pixmap = Icons.load("Caution2.png") self.up_button = qt.QPushButton(self, "up_button") self.up_button.setPixmap(self.up_pixmap) self.up_button.setFixedHeight(25) self.delete_button = qt.QPushButton(self, "delete_button") self.delete_button.setPixmap(self.delete_pixmap) self.delete_button.setDisabled(True) qt.QToolTip.add(self.delete_button, "Delete highlighted queue entries") self.down_button = qt.QPushButton(self, "down_button") self.down_button.setPixmap(self.down_pixmap) self.down_button.setFixedHeight(25) self.collect_button = qt.QPushButton(self, "collect_button") self.collect_button.setText("Collect Queue") self.collect_button.setFixedWidth(125) self.collect_button.setIconSet(qt.QIconSet(self.play_pixmap)) self.collect_button.setPaletteBackgroundColor( widget_colors.LIGHT_GREEN) self.continue_button = qt.QPushButton(self, "ok_button") self.continue_button.setText('Pause') self.continue_button.setEnabled(True) self.continue_button.setFixedWidth(75) qt.QToolTip.add(self.continue_button, "Pause after current data collection") self.sample_list_view = qt.QListView(self, "sample_list_view") self.sample_list_view.setSelectionMode(qt.QListView.Extended) self.setSizePolicy( qt.QSizePolicy(qt.QSizePolicy.Fixed, qt.QSizePolicy.Expanding)) self.sample_list_view.setSizePolicy( qt.QSizePolicy(qt.QSizePolicy.Fixed, qt.QSizePolicy.Expanding)) self.sample_list_view.setSorting(-1) self.sample_list_view.addColumn("", 280) self.sample_list_view.addColumn("", 130) self.sample_list_view.header().hide() self.sample_list_view.header().hide() self.sample_list_view.setFrameShape(qt.QListView.StyledPanel) self.sample_list_view.setFrameShadow(qt.QListView.Sunken) self.sample_list_view.setRootIsDecorated(1) self.sample_list_view.setSelected(self.sample_list_view.firstChild(), True) layout = qt.QVBoxLayout(self, 0, 0, 'main_layout') button_layout = qt.QHBoxLayout(None, 0, 0, 'button_layout') button_layout.addWidget(self.up_button) button_layout.addWidget(self.down_button) layout.setSpacing(10) layout.addWidget(self.sample_list_view) self.buttons_grid_layout = qt.QGridLayout(2, 5) layout.addLayout(self.buttons_grid_layout) self.buttons_grid_layout.addLayout(button_layout, 0, 0) self.buttons_grid_layout.addWidget(self.delete_button, 0, 4) self.buttons_grid_layout.addWidget(self.collect_button, 1, 0) self.buttons_grid_layout.addWidget(self.continue_button, 1, 4) self.clearWState(qt.Qt.WState_Polished) qt.QObject.connect(self.up_button, qt.SIGNAL("clicked()"), self.up_click) qt.QObject.connect(self.down_button, qt.SIGNAL("clicked()"), self.down_click) qt.QObject.connect(self.delete_button, qt.SIGNAL("clicked()"), self.delete_click) qt.QObject.connect(self.collect_button, qt.SIGNAL("clicked()"), self.collect_stop_toggle) qt.QObject.connect(self.sample_list_view, qt.SIGNAL("selectionChanged()"), self.sample_list_view_selection) qt.QObject.connect( self.sample_list_view, qt.SIGNAL( "contextMenuRequested(QListViewItem *, const QPoint& , int)"), self.show_context_menu) qt.QObject.connect( self.sample_list_view, qt.SIGNAL("itemRenamed(QListViewItem *, int , const QString& )"), self.item_renamed) qt.QObject.connect( self.sample_list_view, qt.SIGNAL("doubleClicked(QListViewItem *, const QPoint &, int)"), self.item_double_click) qt.QObject.connect( self.sample_list_view, qt.SIGNAL( "mouseButtonClicked(int, QListViewItem *, const QPoint &, int)" ), self.item_click) qt.QObject.connect(self.confirm_dialog, qt.PYSIGNAL("continue_clicked"), self.collect_items) qt.QObject.connect(self.continue_button, qt.SIGNAL("clicked()"), self.continue_button_click) self.sample_list_view.viewport().installEventFilter(self) self.setFixedWidth(415) self.collect_button.setDisabled(True)
def setup(self): self.detailsPopup = None self.setDetailsPopup(self.getSavedDICOMDetailsWidgetType()()) # XXX Slicer 4.5 - Remove these. Here only for backward compatibility. self.dicomBrowser = self.detailsPopup.dicomBrowser self.tables = self.detailsPopup.tables layoutManager = slicer.app.layoutManager() if layoutManager is not None: layoutManager.layoutChanged.connect(self.onLayoutChanged) # connect to the 'Show DICOM Browser' button self.showBrowserButton = qt.QPushButton('Show DICOM database browser') self.showBrowserButton.setCheckable(True) self.layout.addWidget(self.showBrowserButton) self.showBrowserButton.setStyleSheet("font:Bold;" "font-size:12px") self.showBrowserButton.connect('clicked()', self.toggleDetailsPopup) self.loadedDataLabel = qt.QLabel("Loaded data") self.loadedDataLabel.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Fixed) self.layout.addWidget(self.loadedDataLabel) font = qt.QFont() font.setBold(True) font.setPointSize(12) self.loadedDataLabel.setFont(font) self.layout.addWidget(self.loadedDataLabel) self.subjectHierarchyTree = slicer.qMRMLSubjectHierarchyTreeView() self.layout.addWidget(self.subjectHierarchyTree) self.subjectHierarchyTree.setMRMLScene(slicer.mrmlScene) self.subjectHierarchyTree.currentItemChanged.connect( self.onCurrentItemChanged) self.subjectHierarchyTree.currentItemModified.connect( self.onCurrentItemModified) self.subjectHierarchyCurrentVisibility = False self.subjectHierarchyTree.setColumnHidden( self.subjectHierarchyTree.model().idColumn, True) self.browserSettingsWidget = ctk.ctkCollapsibleGroupBox() self.browserSettingsWidget.title = "Browser settings" self.layout.addWidget(self.browserSettingsWidget) self.browserSettingsWidget.collapsed = True self.browserSettingsWidget.setLayout(qt.QFormLayout()) self.directoryButton = ctk.ctkDirectoryButton() self.browserSettingsWidget.layout().addRow("Local database:", self.directoryButton) self.directoryButton.directoryChanged.connect( self.onDatabaseDirectoryButtonChanged) self.onDatabaseDirectoryDetailsPopupChanged( self.detailsPopup.dicomBrowser.databaseDirectory) self.tableDensityComboBox = qt.QComboBox() self.browserSettingsWidget.layout().addRow("Table density:", self.tableDensityComboBox) self.tableDensityComboBox.currentIndexChanged.connect( self.onTableDensityChanged) self.updateTableDensityComboBox() self.horizontalCheckBox = qt.QCheckBox() self.horizontalCheckBox.checked = settingsValue( 'DICOM/horizontalTables', 0, converter=int) self.horizontalCheckBox.stateChanged.connect( self.onHorizontalStateChanged) self.browserSettingsWidget.layout().addRow("Horizontal:", self.horizontalCheckBox) self.browserPersistentCheckBox = qt.QCheckBox() self.browserPersistentCheckBox.checked = settingsValue( 'DICOM/BrowserPersistent', False, converter=toBool) self.browserPersistentCheckBox.stateChanged.connect( self.onBrowserPersistentStateChanged) self.browserSettingsWidget.layout().addRow( "Browser persistent:", self.browserPersistentCheckBox) self.additionalSettingsLayout = qt.QHBoxLayout() # # servers # # testing server - not exposed (used for development) self.localFrame = ctk.ctkCollapsibleButton(self.parent) self.localFrame.setLayout(qt.QVBoxLayout()) self.localFrame.setText("Servers") self.layout.addWidget(self.localFrame) self.localFrame.collapsed = True self.toggleServer = qt.QPushButton("Start Testing Server") self.localFrame.layout().addWidget(self.toggleServer) self.toggleServer.connect('clicked()', self.onToggleServer) self.verboseServer = qt.QCheckBox("Verbose") self.localFrame.layout().addWidget(self.verboseServer) # advanced options - not exposed to end users # developers can uncomment these lines to access testing server self.toggleServer.hide() self.verboseServer.hide() # Listener settings = qt.QSettings() self.toggleListener = qt.QPushButton() self.toggleListener.checkable = True if hasattr(slicer, 'dicomListener'): self.toggleListener.text = "Stop Listener" slicer.dicomListener.process.connect( 'stateChanged(QProcess::ProcessState)', self.onListenerStateChanged) else: self.toggleListener.text = "Start Listener" self.localFrame.layout().addWidget(self.toggleListener) self.toggleListener.connect('clicked()', self.onToggleListener) self.runListenerAtStart = qt.QCheckBox( "Start Listener when Slicer Starts") self.localFrame.layout().addWidget(self.runListenerAtStart) self.runListenerAtStart.checked = settingsValue( 'DICOM/RunListenerAtStart', False, converter=toBool) self.runListenerAtStart.connect('clicked()', self.onRunListenerAtStart) # connect to the main window's dicom button mw = slicer.util.mainWindow() if mw: try: action = slicer.util.findChildren(mw, name='LoadDICOMAction')[0] action.connect('triggered()', self.onOpenDetailsPopup) except IndexError: logging.error( 'Could not connect to the main window DICOM button') if hasattr(slicer, 'dicomListener'): slicer.dicomListener.fileToBeAddedCallback = self.onListenerToAddFile slicer.dicomListener.fileAddedCallback = self.onListenerAddedFile slicer.dicomDatabase.connect('databaseChanged()', self.onDatabaseChanged) # the recent activity frame self.activityFrame = ctk.ctkCollapsibleButton(self.parent) self.activityFrame.collapsed = True self.activityFrame.setLayout(qt.QVBoxLayout()) self.activityFrame.setText("Recent DICOM Activity") self.layout.addWidget(self.activityFrame) self.recentActivity = DICOMLib.DICOMRecentActivityWidget( self.activityFrame, detailsPopup=self.detailsPopup) self.activityFrame.layout().addWidget(self.recentActivity) self.requestUpdateRecentActivity()
def setupOptionsFrame(self): self.operationRadioButtons = [] #Fiducial Placement widget self.fiducialPlacementToggle = slicer.qSlicerMarkupsPlaceWidget() self.fiducialPlacementToggle.setMRMLScene(slicer.mrmlScene) self.fiducialPlacementToggle.placeMultipleMarkups = self.fiducialPlacementToggle.ForcePlaceMultipleMarkups self.fiducialPlacementToggle.buttonsVisible = False self.fiducialPlacementToggle.show() self.fiducialPlacementToggle.placeButton().show() self.fiducialPlacementToggle.deleteButton().show() # Edit surface button self.editButton = qt.QPushButton("Edit") self.editButton.objectName = self.__class__.__name__ + 'Edit' self.editButton.setToolTip("Edit the previously placed group of fiducials.") fiducialAction = qt.QHBoxLayout() fiducialAction.addWidget(self.fiducialPlacementToggle) fiducialAction.addWidget(self.editButton) self.scriptedEffect.addLabeledOptionsWidget("Fiducial Placement: ", fiducialAction) #Operation buttons self.eraseInsideButton = qt.QRadioButton("Erase inside") self.operationRadioButtons.append(self.eraseInsideButton) self.buttonToOperationNameMap[self.eraseInsideButton] = 'ERASE_INSIDE' self.eraseOutsideButton = qt.QRadioButton("Erase outside") self.operationRadioButtons.append(self.eraseOutsideButton) self.buttonToOperationNameMap[self.eraseOutsideButton] = 'ERASE_OUTSIDE' self.fillInsideButton = qt.QRadioButton("Fill inside") self.operationRadioButtons.append(self.fillInsideButton) self.buttonToOperationNameMap[self.fillInsideButton] = 'FILL_INSIDE' self.fillOutsideButton = qt.QRadioButton("Fill outside") self.operationRadioButtons.append(self.fillOutsideButton) self.buttonToOperationNameMap[self.fillOutsideButton] = 'FILL_OUTSIDE' self.setButton = qt.QRadioButton("Set") self.operationRadioButtons.append(self.setButton) self.buttonToOperationNameMap[self.setButton] = 'SET' #Operation buttons layout operationLayout = qt.QGridLayout() operationLayout.addWidget(self.eraseInsideButton, 0, 0) operationLayout.addWidget(self.eraseOutsideButton, 1, 0) operationLayout.addWidget(self.fillInsideButton, 0, 1) operationLayout.addWidget(self.fillOutsideButton, 1, 1) operationLayout.addWidget(self.setButton, 0, 2) self.scriptedEffect.addLabeledOptionsWidget("Operation:", operationLayout) # Apply button self.applyButton = qt.QPushButton("Apply") self.applyButton.objectName = self.__class__.__name__ + 'Apply' self.applyButton.setToolTip("Generate surface from markup fiducials.") self.scriptedEffect.addOptionsWidget(self.applyButton) # Cancel button self.cancelButton = qt.QPushButton("Cancel") self.cancelButton.objectName = self.__class__.__name__ + 'Cancel' self.cancelButton.setToolTip("Clear fiducials and remove from scene.") #Finish action buttons finishAction = qt.QHBoxLayout() finishAction.addWidget(self.cancelButton) finishAction.addWidget(self.applyButton) self.scriptedEffect.addOptionsWidget(finishAction) # connections for button in self.operationRadioButtons: button.connect('toggled(bool)', lambda toggle, widget=self.buttonToOperationNameMap[button]: self.onOperationSelectionChanged(widget, toggle)) self.applyButton.connect('clicked()', self.onApply) self.cancelButton.connect('clicked()', self.onCancel) self.editButton.connect('clicked()', self.onEdit) self.fiducialPlacementToggle.placeButton().clicked.connect(self.onFiducialPlacementToggleChanged)