def create(self): super(PETTumorSegmentationEffectOptions, self).create() #Save space in the GUI self.frame.layout().setSpacing(0) self.frame.layout().setMargin(0) # 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) self.frame.layout().addWidget(self.refinementBoxesFrame) #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.widgets.append(self.noRefinementRadioButton) self.widgets.append(self.globalRefinementRadioButton) self.widgets.append(self.localRefinementRadioButton) self.noRefinementRadioButton.connect('clicked()', self.onRefinementTypeChanged) self.localRefinementRadioButton.connect('clicked()', self.onRefinementTypeChanged) self.globalRefinementRadioButton.connect('clicked()', self.onRefinementTypeChanged) #options are hidden (collapsed) until requested self.optFrame = ctk.ctkCollapsibleButton(self.frame) self.optFrame.setText("Options") self.optFrame.setLayout(qt.QVBoxLayout()) self.optFrame.layout().setSpacing(0) self.optFrame.layout().setMargin(0) self.optFrame.visible = True self.optFrame.collapsed = True self.optFrame.collapsedHeight = 0 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) self.widgets.append(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) self.widgets.append(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) self.widgets.append(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.widgets.append(self.allowOverwritingCheckBox) #advanced options, for abnormal cases such as massive necrotic objects or #low-transition scans like phantoms #infrequently used, just keep vertical self.advFrame = ctk.ctkCollapsibleButton(self.optFrame) self.advFrame.setText("Advanced") self.advFrame.setLayout(qt.QVBoxLayout()) self.advFrame.layout().setSpacing(0) self.advFrame.layout().setMargin(0) self.advFrame.visible = True self.advFrame.collapsed = True self.advFrame.collapsedHeight = 0 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) self.widgets.append(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) self.widgets.append(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.widgets.append(self.linearCostCheckBox) self.optFrame.layout().addWidget(self.advFrame) #apply button kept at bottom of all options self.applyButton = qt.QPushButton("Apply", self.optFrame) self.optFrame.layout().addWidget(self.applyButton) self.applyButton.connect('clicked()', self.onApply) self.widgets.append(self.applyButton) self.applyButton.setToolTip( "Redo last segmentation with the same center and refinement points with any changes in options." ) #When changing settings, update the MRML with it self.assistCenteringCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.allowOverwritingCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.splittingCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.sealingCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.necroticRegionCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.denoiseThresholdCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.linearCostCheckBox.connect('toggled(bool)', self.updateMRMLFromGUI) self.frame.layout().addWidget(self.optFrame) HelpButton( self.frame, "Click on a lesion in a PET scan to segment it. 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. For more information: http://www.slicer.org/slicerWiki/index.php/Documentation/4.4/Modules/PETTumorSegmentationEffect" ) # Add vertical spacer self.frame.layout().addStretch(1) # Clear any existing data and undo/redo queue; working directly with other tools is # beyond the scope of this self.logic.reset() self.updateGUIFromMRML(self, 0)
def createUserInterface(self): self.__layout = self.__parent.createUserInterface() step_label = qt.QLabel( """Review your segmentation. Use the 3D Visualization slider to see your segmentation in context with your image. Use the Editor panel to apply spot edits to your segmentation. If you would like to start over, see the Restart box below""" ) step_label.setWordWrap(True) self.__primaryGroupBox = qt.QGroupBox() self.__primaryGroupBox.setTitle('Information') self.__primaryGroupBoxLayout = qt.QFormLayout(self.__primaryGroupBox) self.__primaryGroupBoxLayout.addRow(step_label) self.__layout.addRow(self.__primaryGroupBox) # self.__threshRange = slicer.qMRMLRangeWidget() # self.__threshRange.decimals = 0 # self.__threshRange.singleStep = 1 # self.__threshRange.connect('valuesChanged(double,double)', self.onThresholdChanged) # qt.QTimer.singleShot(0, self.killButton) # ThreshGroupBox = qt.QGroupBox() # ThreshGroupBox.setTitle('3D Visualization Intensity Threshold') # ThreshGroupBoxLayout = qt.QFormLayout(ThreshGroupBox) # ThreshGroupBoxLayout.addRow(self.__threshRange) # self.__layout.addRow(ThreshGroupBox) editorWidgetParent = slicer.qMRMLWidget() editorWidgetParent.setLayout(qt.QVBoxLayout()) editorWidgetParent.setMRMLScene(slicer.mrmlScene) self.EditorWidget = EditorWidget(parent=editorWidgetParent) self.EditorWidget.setup() self.__layout.addRow(editorWidgetParent) RestartGroupBox = qt.QGroupBox() RestartGroupBox.setTitle('Restart') RestartGroupBoxLayout = qt.QFormLayout(RestartGroupBox) self.__RestartButton = qt.QPushButton('Return to Step 1') RestartGroupBoxLayout.addRow(self.__RestartButton) self.__RemoveRegisteredImage = qt.QCheckBox() self.__RemoveRegisteredImage.checked = True self.__RemoveRegisteredImage.setToolTip( "Delete your registered images.") RestartGroupBoxLayout.addRow("Delete Registered images: ", self.__RemoveRegisteredImage) self.__RemoveNormalizedImages = qt.QCheckBox() self.__RemoveNormalizedImages.checked = True self.__RemoveNormalizedImages.setToolTip( "Delete your normalized images.") RestartGroupBoxLayout.addRow("Delete Normalized images: ", self.__RemoveNormalizedImages) self.__RemoveSubtractionMap = qt.QCheckBox() self.__RemoveSubtractionMap.checked = True self.__RemoveSubtractionMap.setToolTip("Delete your subtraction map.") RestartGroupBoxLayout.addRow("Delete Subtraction map: ", self.__RemoveSubtractionMap) self.__RemoveCroppedMap = qt.QCheckBox() self.__RemoveCroppedMap.checked = True self.__RemoveCroppedMap.setToolTip( "Delete the cropped version of your input volume.") RestartGroupBoxLayout.addRow("Delete Cropped Volume: ", self.__RemoveCroppedMap) self.__RemoveROI = qt.QCheckBox() self.__RemoveROI.checked = False self.__RemoveROI.setToolTip( "Delete the ROI you made with your markup points.") RestartGroupBoxLayout.addRow("Delete Full ROI: ", self.__RemoveROI) self.__RemoveThresholdedROI = qt.QCheckBox() self.__RemoveThresholdedROI.checked = False self.__RemoveThresholdedROI.setToolTip( "Delete the intensity-thresholded version of your ROI.") RestartGroupBoxLayout.addRow("Delete Thresholded ROI: ", self.__RemoveThresholdedROI) self.__RemoveMarkups = qt.QCheckBox() self.__RemoveMarkups.checked = True self.__RemoveMarkups.setToolTip( "Delete the markup points you used to create your 3D ROI.") RestartGroupBoxLayout.addRow("Delete Markup Points: ", self.__RemoveMarkups) self.__RemoveModels = qt.QCheckBox() self.__RemoveModels.checked = True self.__RemoveModels.setToolTip( "Delete the 3D model you created from your markup points.") RestartGroupBoxLayout.addRow("Delete 3D Model: ", self.__RemoveModels) self.__RestartButton.connect('clicked()', self.Restart) self.__RestartActivated = True self.__layout.addRow(RestartGroupBox)
def setup(self): # # 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 = False 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() if hasattr(slicer, 'dicomListener'): self.toggleListener.text = "Stop Listener" slicer.dicomListener.process.connect('stateChanged(int)', 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) if settings.contains('DICOM/RunListenerAtStart'): self.runListenerAtStart.checked = bool( settings.value('DICOM/RunListenerAtStart')) self.runListenerAtStart.connect('clicked()', self.onRunListenerAtStart) # the Database frame (home of the ctkDICOM widget) self.dicomFrame = ctk.ctkCollapsibleButton(self.parent) self.dicomFrame.setLayout(qt.QVBoxLayout()) self.dicomFrame.setText("DICOM Database and Networking") self.layout.addWidget(self.dicomFrame) # initialize the dicomDatabase # - don't let the user escape without # picking a valid database directory while not slicer.dicomDatabase: self.promptForDatabaseDirectory() # # create and configure the app widget - this involves # reaching inside and manipulating the widget hierarchy # - TODO: this configurability should be exposed more natively # in the CTK code to avoid the findChildren calls # self.dicomApp = ctk.ctkDICOMAppWidget() if self.hideSearch: # hide the search options - doesn't work yet and doesn't fit # well into the frame slicer.util.findChildren(self.dicomApp, 'SearchOption')[0].hide() self.detailsPopup = DICOMLib.DICOMDetailsPopup( self.dicomApp, setBrowserPersistence=self.setBrowserPersistence) self.tree = self.detailsPopup.tree self.showBrowser = qt.QPushButton('Show DICOM Browser') self.dicomFrame.layout().addWidget(self.showBrowser) self.showBrowser.connect('clicked()', self.detailsPopup.open) # make the tree view a bit bigger self.tree.setMinimumHeight(250) if hasattr(slicer, 'dicomListener'): slicer.dicomListener.fileToBeAddedCallback = self.onListenerToAddFile slicer.dicomListener.fileAddedCallback = self.onListenerAddedFile self.contextMenu = qt.QMenu(self.tree) self.exportAction = qt.QAction("Export to Study", self.contextMenu) self.contextMenu.addAction(self.exportAction) self.exportAction.enabled = False self.deleteAction = qt.QAction("Delete", self.contextMenu) self.contextMenu.addAction(self.deleteAction) self.contextMenu.connect('triggered(QAction*)', self.onContextMenuTriggered) slicer.dicomDatabase.connect('databaseChanged()', self.onDatabaseChanged) self.dicomApp.connect('databaseDirectoryChanged(QString)', self.onDatabaseDirectoryChanged) selectionModel = self.tree.selectionModel() # TODO: can't use this because QList<QModelIndex> is not visible in PythonQt #selectionModel.connect('selectionChanged(QItemSelection, QItemSelection)', self.onTreeSelectionChanged) self.tree.connect('clicked(QModelIndex)', self.onTreeClicked) self.tree.setContextMenuPolicy(3) self.tree.connect('customContextMenuRequested(QPoint)', self.onTreeContextMenuRequested) # enable to the Send button of the app widget and take it over # for our purposes - TODO: fix this to enable it at the ctkDICOM level self.sendButton = slicer.util.findChildren(self.dicomApp, text='Send')[0] self.sendButton.enabled = False self.sendButton.connect('clicked()', self.onSendClicked) # the recent activity frame self.activityFrame = ctk.ctkCollapsibleButton(self.parent) 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.widget) self.requestUpdateRecentActivity() # Add spacer to layout self.layout.addStretch(1)
def create(self): super(PaintEffectOptions, self).create() labelVolume = self.editUtil.getLabelVolume() if labelVolume and labelVolume.GetImageData(): spacing = labelVolume.GetSpacing() dimensions = labelVolume.GetImageData().GetDimensions() self.minimumRadius = 0.5 * min(spacing) bounds = [a * b for a, b in zip(spacing, dimensions)] self.maximumRadius = 0.5 * max(bounds) else: self.minimumRadius = 0.01 self.maximumRadius = 100 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.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.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.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.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.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.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.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) EditorLib.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) # set the node parameters that are dependent on the input data self.parameterNode.SetParameter("PaintEffect,radius", str(self.minimumRadius * 10))
def setup(self): self.FilteringFrame = qt.QFrame() self.FilteringFrame.setLayout(qt.QVBoxLayout()) self.FilteringFrame.enabled = False self.FilteringFrame.setObjectName('FilteringFrame') self.FilteringFrame.setStyleSheet( '#FilteringFrame {border: 1px solid lightGray; color: black; }') self.layout.addWidget(self.FilteringFrame) filterLabel = qt.QLabel() filterLabel.setText('Filtering') self.FilteringFrame.layout().addWidget(filterLabel) radioButtonsGroup = qt.QGroupBox() radioButtonsGroup.setLayout(qt.QHBoxLayout()) radioButtonsGroup.setFixedWidth(120) radioButtonsGroup.setObjectName('radioButtonsGroup') radioButtonsGroup.setStyleSheet( '#radioButtonsGroup {border: 1px solid white; color: black; }') self.filterOnRadioButton = qt.QRadioButton() self.filterOnRadioButton.setText('On') self.filterOnRadioButton.setChecked(0) radioButtonsGroup.layout().addWidget(self.filterOnRadioButton) self.filterOffRadioButton = qt.QRadioButton() self.filterOffRadioButton.setText('Off') self.filterOffRadioButton.setChecked(1) radioButtonsGroup.layout().addWidget(self.filterOffRadioButton) self.FilteringFrame.layout().addWidget(radioButtonsGroup) self.filterOptionsFrame = qt.QFrame() self.filterOptionsFrame.setLayout(qt.QVBoxLayout()) self.filterOptionsFrame.setObjectName('filterOptionsFrame') self.filterOptionsFrame.setStyleSheet( '#filterOptionsFrame {border: 0.5px solid lightGray; color: black; }' ) self.filterOptionsFrame.hide() self.FilteringFrame.layout().addWidget(self.filterOptionsFrame) self.filterApplication = qt.QCheckBox() self.filterApplication.setText('Filter for Phenotype Analysis') self.filterApplication.setChecked(0) self.filterOptionsFrame.layout().addWidget(self.filterApplication) filterOptionsGroup = qt.QGroupBox() filterOptionsGroup.setLayout(qt.QHBoxLayout()) filterOptionsGroup.setFixedWidth(220) filterOptionsGroup.setObjectName('filterOptionsGroup') filterOptionsGroup.setStyleSheet( '#filterOptionsGroup {border: 1px solid white; color: black; }') self.NLMFilterRadioButton = qt.QRadioButton() self.NLMFilterRadioButton.setText('NLM') self.NLMFilterRadioButton.setChecked(1) filterOptionsGroup.layout().addWidget(self.NLMFilterRadioButton) self.MedianFilterRadioButton = qt.QRadioButton() self.MedianFilterRadioButton.setText('Median') self.MedianFilterRadioButton.setChecked(0) filterOptionsGroup.layout().addWidget(self.MedianFilterRadioButton) self.GaussianFilterRadioButton = qt.QRadioButton() self.GaussianFilterRadioButton.setText('Gaussian') self.GaussianFilterRadioButton.setChecked(0) filterOptionsGroup.layout().addWidget(self.GaussianFilterRadioButton) self.filterOptionsFrame.layout().addWidget(filterOptionsGroup) # Filter Params FilterParams = qt.QFrame() FilterParams.setLayout(qt.QVBoxLayout()) self.filterOptionsFrame.layout().addWidget(FilterParams) DimGroupBox = qt.QGroupBox() DimGroupBox.setLayout(qt.QHBoxLayout()) DimGroupBox.setFixedWidth(180) DimGroupBox.setObjectName('DimGroupBox') DimGroupBox.setStyleSheet( '#DimGroupBox {border: 1px solid white; color: black; }') FilterParams.layout().addWidget(DimGroupBox) FilterDimensionLabel = qt.QLabel() FilterDimensionLabel.setText('Dimensions: ') FilterDimensionLabel.setToolTip( 'Choose if the filter has to operate in 2D or 3D.') DimGroupBox.layout().addWidget(FilterDimensionLabel) self.Filt2DOption = qt.QPushButton() self.Filt2DOption.setText('2D') self.Filt2DOption.setCheckable(1) self.Filt2DOption.setChecked(1) self.Filt2DOption.setAutoExclusive(1) self.Filt2DOption.setFixedWidth(45) DimGroupBox.layout().addWidget(self.Filt2DOption) self.Filt3DOption = qt.QPushButton() self.Filt3DOption.setText('3D') self.Filt3DOption.setCheckable(1) self.Filt3DOption.setChecked(0) self.Filt3DOption.setFixedWidth(45) self.Filt3DOption.setAutoExclusive(1) DimGroupBox.layout().addWidget(self.Filt3DOption) StrengthGroupBox = qt.QGroupBox() StrengthGroupBox.setLayout(qt.QHBoxLayout()) StrengthGroupBox.setFixedWidth(270) StrengthGroupBox.setObjectName('StrengthGroupBox') StrengthGroupBox.setStyleSheet( '#StrengthGroupBox {border: 1px solid white; color: black; }') FilterParams.layout().addWidget(StrengthGroupBox) FilterStrengthLabel = qt.QLabel() FilterStrengthLabel.setText('Strength: ') FilterStrengthLabel.setToolTip( 'Choose strength of the filtering process.') StrengthGroupBox.layout().addWidget(FilterStrengthLabel) self.SmoothOption = qt.QPushButton() self.SmoothOption.setText('Smooth') self.SmoothOption.setCheckable(1) self.SmoothOption.setChecked(1) self.SmoothOption.setAutoExclusive(1) self.SmoothOption.setFixedWidth(60) StrengthGroupBox.layout().addWidget(self.SmoothOption) self.MediumOption = qt.QPushButton() self.MediumOption.setText('Medium') self.MediumOption.setCheckable(1) self.MediumOption.setChecked(0) self.MediumOption.setFixedWidth(60) self.MediumOption.setAutoExclusive(1) StrengthGroupBox.layout().addWidget(self.MediumOption) self.HeavyOption = qt.QPushButton() self.HeavyOption.setText('Heavy') self.HeavyOption.setCheckable(1) self.HeavyOption.setChecked(0) self.HeavyOption.setFixedWidth(60) self.HeavyOption.setAutoExclusive(1) StrengthGroupBox.layout().addWidget(self.HeavyOption) # Downsampling option for label map creation self.LMCreationFrame = qt.QFrame() self.LMCreationFrame.setLayout(qt.QVBoxLayout()) self.LMCreationFrame.enabled = False self.LMCreationFrame.setObjectName('LMCreationFrame') self.LMCreationFrame.setStyleSheet( '#LMCreationFrame {border: 1px solid lightGray; color: black; }') self.parent.layout().addWidget(self.LMCreationFrame) LMCreationLabel = qt.QLabel() LMCreationLabel.setText('Label Map Creation:') self.LMCreationFrame.layout().addWidget(LMCreationLabel) self.DownSamplingGroupBox = qt.QGroupBox() self.DownSamplingGroupBox.setLayout(qt.QHBoxLayout()) self.DownSamplingGroupBox.setFixedWidth(130) self.DownSamplingGroupBox.setObjectName('DownSamplingGroupBox') self.DownSamplingGroupBox.setStyleSheet( '#DownSamplingGroupBox {border: 1px solid white; color: black; }') self.DownSamplingGroupBox.setToolTip( 'Choose between fast and slow label map creation.') self.LMCreationFrame.layout().addWidget(self.DownSamplingGroupBox) self.FastOption = qt.QRadioButton() self.FastOption.setText('Fast') self.FastOption.setCheckable(1) self.FastOption.setChecked(0) self.DownSamplingGroupBox.layout().addWidget(self.FastOption) self.SlowOption = qt.QRadioButton() self.SlowOption.setText('Slow') self.SlowOption.setCheckable(1) self.SlowOption.setChecked(1) self.DownSamplingGroupBox.layout().addWidget(self.SlowOption) self.filterOnRadioButton.connect('toggled(bool)', self.showFilterParams) self.filterOffRadioButton.connect('toggled(bool)', self.hideFilterParams)
def setup(self): if self.developerMode: self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "SurfaceToolbox Reload" self.layout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) self.reloadAndTestButton = qt.QPushButton("Reload and Test") self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests." self.layout.addWidget(self.reloadAndTestButton) self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest) inputModelSelectorFrame = qt.QFrame(self.parent) inputModelSelectorFrame.setLayout(qt.QHBoxLayout()) self.parent.layout().addWidget(inputModelSelectorFrame) inputModelSelectorLabel = qt.QLabel("Input Model: ", inputModelSelectorFrame) inputModelSelectorLabel.setToolTip("Select the input model") inputModelSelectorFrame.layout().addWidget(inputModelSelectorLabel) inputModelSelector = slicer.qMRMLNodeComboBox(inputModelSelectorFrame) inputModelSelector.nodeTypes = (("vtkMRMLModelNode"), "") inputModelSelector.selectNodeUponCreation = False inputModelSelector.addEnabled = False inputModelSelector.removeEnabled = False inputModelSelector.noneEnabled = True inputModelSelector.showHidden = False inputModelSelector.showChildNodeTypes = False inputModelSelector.setMRMLScene(slicer.mrmlScene) inputModelSelectorFrame.layout().addWidget(inputModelSelector) outputModelSelectorFrame = qt.QFrame(self.parent) outputModelSelectorFrame.setLayout(qt.QHBoxLayout()) self.parent.layout().addWidget(outputModelSelectorFrame) outputModelSelectorLabel = qt.QLabel("Output Model: ", outputModelSelectorFrame) outputModelSelectorLabel.setToolTip("Select the output model") outputModelSelectorFrame.layout().addWidget(outputModelSelectorLabel) outputModelSelector = slicer.qMRMLNodeComboBox( outputModelSelectorFrame) outputModelSelector.nodeTypes = (("vtkMRMLModelNode"), "") outputModelSelector.selectNodeUponCreation = False outputModelSelector.addEnabled = True outputModelSelector.renameEnabled = True outputModelSelector.removeEnabled = True outputModelSelector.noneEnabled = True outputModelSelector.showHidden = False outputModelSelector.showChildNodeTypes = False outputModelSelector.baseName = "Model" outputModelSelector.selectNodeUponCreation = True outputModelSelector.setMRMLScene(slicer.mrmlScene) outputModelSelectorFrame.layout().addWidget(outputModelSelector) decimationButton = qt.QPushButton("Decimation") decimationButton.checkable = True self.layout.addWidget(decimationButton) decimationFrame = qt.QFrame(self.parent) self.layout.addWidget(decimationFrame) decimationFormLayout = qt.QFormLayout(decimationFrame) reductionFrame, reductionSlider, reductionSpinBox = numericInputFrame( self.parent, "Reduction:", "Tooltip", 0.0, 1.0, 0.1, 1) decimationFormLayout.addWidget(reductionFrame) boundaryDeletionCheckBox = qt.QCheckBox("Boundary deletion") decimationFormLayout.addWidget(boundaryDeletionCheckBox) smoothingButton = qt.QPushButton("Smoothing") smoothingButton.checkable = True self.layout.addWidget(smoothingButton) smoothingFrame = qt.QFrame(self.parent) self.layout.addWidget(smoothingFrame) smoothingFormLayout = qt.QFormLayout(smoothingFrame) smoothingMethodCombo = qt.QComboBox(smoothingFrame) smoothingMethodCombo.addItem("Laplace") smoothingMethodCombo.addItem("Taubin") smoothingFormLayout.addWidget(smoothingMethodCombo) laplaceMethodFrame = qt.QFrame(self.parent) smoothingFormLayout.addWidget(laplaceMethodFrame) laplaceMethodFormLayout = qt.QFormLayout(laplaceMethodFrame) laplaceIterationsFrame, laplaceIterationsSlider, laplaceIterationsSpinBox = numericInputFrame( self.parent, "Iterations:", "Tooltip", 0.0, 500.0, 1.0, 0) laplaceMethodFormLayout.addWidget(laplaceIterationsFrame) laplaceRelaxationFrame, laplaceRelaxationSlider, laplaceRelaxationSpinBox = numericInputFrame( self.parent, "Relaxation:", "Tooltip", 0.0, 1.0, 0.1, 1) laplaceMethodFormLayout.addWidget(laplaceRelaxationFrame) taubinMethodFrame = qt.QFrame(self.parent) smoothingFormLayout.addWidget(taubinMethodFrame) taubinMethodFormLayout = qt.QFormLayout(taubinMethodFrame) taubinIterationsFrame, taubinIterationsSlider, taubinIterationsSpinBox = numericInputFrame( self.parent, "Iterations:", "Tooltip", 0.0, 100.0, 1.0, 0) taubinMethodFormLayout.addWidget(taubinIterationsFrame) taubinPassBandFrame, taubinPassBandSlider, taubinPassBandSpinBox = numericInputFrame( self.parent, "Pass Band:", "Tooltip", 0.0, 1.0, 0.01, 2) taubinMethodFormLayout.addWidget(taubinPassBandFrame) boundarySmoothingCheckBox = qt.QCheckBox("Boundary Smoothing") smoothingFormLayout.addWidget(boundarySmoothingCheckBox) normalsButton = qt.QPushButton("Normals") normalsButton.checkable = True self.layout.addWidget(normalsButton) normalsFrame = qt.QFrame(self.parent) self.layout.addWidget(normalsFrame) normalsFormLayout = qt.QFormLayout(normalsFrame) flipNormalsCheckBox = qt.QCheckBox("Flip Normals") normalsFormLayout.addWidget(flipNormalsCheckBox) splittingCheckBox = qt.QCheckBox("Splitting") normalsFormLayout.addWidget(splittingCheckBox) featureAngleFrame, featureAngleSlider, featureAngleSpinBox = numericInputFrame( self.parent, "Feature Angle:", "Tooltip", 0.0, 180.0, 1.0, 0) normalsFormLayout.addWidget(featureAngleFrame) cleanerButton = qt.QPushButton("Cleaner") cleanerButton.checkable = True self.layout.addWidget(cleanerButton) connectivityButton = qt.QPushButton("Connectivity") connectivityButton.checkable = True self.layout.addWidget(connectivityButton) #connectivityFrame = qt.QFrame(self.parent) #self.layout.addWidget(connectivityFrame) #connectivityFormLayout = qt.QFormLayout(connectivityFrame) # TODO: connectivity could be # - largest connected # - threshold connected (discard below point count) # - pick a region interactively # - turn a multiple connected surface into a model hierarchy buttonFrame = qt.QFrame(self.parent) buttonFrame.setLayout(qt.QHBoxLayout()) self.layout.addWidget(buttonFrame) toggleModelsButton = qt.QPushButton("Toggle Models") toggleModelsButton.toolTip = "Show original model." buttonFrame.layout().addWidget(toggleModelsButton) applyButton = qt.QPushButton("Apply") applyButton.toolTip = "Filter surface." buttonFrame.layout().addWidget(applyButton) self.layout.addStretch(1) class state(object): inputModelNode = None outputModelNode = None decimation = False reduction = 0.8 boundaryDeletion = False smoothing = False smoothingMethod = "Laplace" laplaceIterations = 100.0 laplaceRelaxation = 0.5 taubinIterations = 30.0 taubinPassBand = 0.1 boundarySmoothing = True normals = False flipNormals = False splitting = False featureAngle = 30.0 cleaner = False connectivity = False scope_locals = locals() def connect(obj, evt, cmd): def callback(*args): current_locals = scope_locals.copy() current_locals.update({'args': args}) exec cmd in globals(), current_locals updateGUI() obj.connect(evt, callback) def updateGUI(): def button_stylesheet(active): if active: return "background-color: green" else: return "" decimationButton.checked = state.decimation #decimationButton.setStyleSheet(button_stylesheet(state.decimation)) decimationFrame.visible = state.decimation boundaryDeletionCheckBox.checked = state.boundaryDeletion reductionSlider.value = state.reduction reductionSpinBox.value = state.reduction smoothingButton.checked = state.smoothing smoothingFrame.visible = state.smoothing laplaceMethodFrame.visible = state.smoothingMethod == "Laplace" laplaceIterationsSlider.value = state.laplaceIterations laplaceIterationsSpinBox.value = state.laplaceIterations laplaceRelaxationSlider.value = state.laplaceRelaxation laplaceRelaxationSpinBox.value = state.laplaceRelaxation taubinMethodFrame.visible = state.smoothingMethod == "Taubin" taubinIterationsSlider.value = state.taubinIterations taubinIterationsSpinBox.value = state.taubinIterations taubinPassBandSlider.value = state.taubinPassBand taubinPassBandSpinBox.value = state.taubinPassBand boundarySmoothingCheckBox.checked = state.boundarySmoothing normalsButton.checked = state.normals normalsFrame.visible = state.normals flipNormalsCheckBox.checked = state.flipNormals splittingCheckBox.checked = state.splitting featureAngleFrame.visible = state.splitting featureAngleSlider.value = state.featureAngle featureAngleSpinBox.value = state.featureAngle cleanerButton.checked = state.cleaner connectivityButton.checked = state.connectivity toggleModelsButton.enabled = state.inputModelNode != None and state.outputModelNode != None applyButton.enabled = state.inputModelNode != None and state.outputModelNode != None connect(inputModelSelector, 'currentNodeChanged(vtkMRMLNode*)', 'state.inputModelNode = args[0]') connect(outputModelSelector, 'currentNodeChanged(vtkMRMLNode*)', 'state.outputModelNode = args[0]') def initializeModelNode(node): displayNode = slicer.vtkMRMLModelDisplayNode() storageNode = slicer.vtkMRMLModelStorageNode() displayNode.SetScene(slicer.mrmlScene) storageNode.SetScene(slicer.mrmlScene) slicer.mrmlScene.AddNode(displayNode) slicer.mrmlScene.AddNode(storageNode) node.SetAndObserveDisplayNodeID(displayNode.GetID()) node.SetAndObserveStorageNodeID(storageNode.GetID()) outputModelSelector.connect('nodeAddedByUser(vtkMRMLNode*)', initializeModelNode) connect(decimationButton, 'clicked(bool)', 'state.decimation = args[0]') connect(reductionSlider, 'valueChanged(double)', 'state.reduction = args[0]') connect(reductionSpinBox, 'valueChanged(double)', 'state.reduction = args[0]') connect(boundaryDeletionCheckBox, 'stateChanged(int)', 'state.boundaryDeletion = bool(args[0])') connect(smoothingButton, 'clicked(bool)', 'state.smoothing = args[0]') connect(smoothingMethodCombo, 'currentIndexChanged(QString)', 'state.smoothingMethod = args[0]') connect(laplaceIterationsSlider, 'valueChanged(double)', 'state.laplaceIterations = int(args[0])') connect(laplaceIterationsSpinBox, 'valueChanged(double)', 'state.laplaceIterations = int(args[0])') connect(laplaceRelaxationSlider, 'valueChanged(double)', 'state.laplaceRelaxation = args[0]') connect(laplaceRelaxationSpinBox, 'valueChanged(double)', 'state.laplaceRelaxation = args[0]') connect(taubinIterationsSlider, 'valueChanged(double)', 'state.taubinIterations = int(args[0])') connect(taubinIterationsSpinBox, 'valueChanged(double)', 'state.taubinIterations = int(args[0])') connect(taubinPassBandSlider, 'valueChanged(double)', 'state.taubinPassBand = args[0]') connect(taubinPassBandSpinBox, 'valueChanged(double)', 'state.taubinPassBand = args[0]') connect(boundarySmoothingCheckBox, 'stateChanged(int)', 'state.boundarySmoothing = bool(args[0])') connect(normalsButton, 'clicked(bool)', 'state.normals = args[0]') connect(flipNormalsCheckBox, 'stateChanged(int)', 'state.flipNormals = bool(args[0])') connect(splittingCheckBox, 'stateChanged(int)', 'state.splitting = bool(args[0])') connect(featureAngleSlider, 'valueChanged(double)', 'state.featureAngle = args[0]') connect(featureAngleSpinBox, 'valueChanged(double)', 'state.featureAngle = args[0]') connect(cleanerButton, 'clicked(bool)', 'state.cleaner = args[0]') connect(connectivityButton, 'clicked(bool)', 'state.connectivity = args[0]') def onApply(): updateGUI() applyButton.text = "Working..." applyButton.repaint() slicer.app.processEvents() logic = SurfaceToolboxLogic() result = logic.applyFilters(state) if result: state.inputModelNode.GetModelDisplayNode().VisibilityOff() state.outputModelNode.GetModelDisplayNode().VisibilityOn() else: state.inputModelNode.GetModelDisplayNode().VisibilityOn() state.outputModelNode.GetModelDisplayNode().VisibilityOff() applyButton.text = "Apply" applyButton.connect('clicked()', onApply) def onToggleModels(): updateGUI() if state.inputModelNode.GetModelDisplayNode().GetVisibility(): state.inputModelNode.GetModelDisplayNode().VisibilityOff() state.outputModelNode.GetModelDisplayNode().VisibilityOn() toggleModelsButton.text = "Toggle Models (Output)" else: state.inputModelNode.GetModelDisplayNode().VisibilityOn() state.outputModelNode.GetModelDisplayNode().VisibilityOff() toggleModelsButton.text = "Toggle Models (Input)" toggleModelsButton.connect('clicked()', onToggleModels) updateGUI() self.updateGUI = updateGUI
def setup(self): # # 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 = False 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(int)',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) if settings.contains('DICOM/RunListenerAtStart'): self.runListenerAtStart.checked = bool(settings.value('DICOM/RunListenerAtStart') == 'true') self.runListenerAtStart.connect('clicked()', self.onRunListenerAtStart) # the Database frame (home of the ctkDICOM widget) self.dicomFrame = ctk.ctkCollapsibleButton(self.parent) self.dicomFrame.setLayout(qt.QVBoxLayout()) self.dicomFrame.setText("DICOM Database and Networking") self.layout.addWidget(self.dicomFrame) # initialize the dicomDatabase # - pick a default and let the user know if not slicer.dicomDatabase: self.promptForDatabaseDirectory() # # create and configure the app widget - this involves # reaching inside and manipulating the widget hierarchy # - TODO: this configurability should be exposed more natively # in the CTK code to avoid the findChildren calls # self.dicomBrowser = ctk.ctkDICOMBrowser() DICOM.setDatabasePrecacheTags(self.dicomBrowser) self.detailsPopup = DICOMLib.DICOMDetailsPopup(self.dicomBrowser) self.tables = self.detailsPopup.tables self.showBrowser = qt.QPushButton('Show DICOM Browser') self.dicomFrame.layout().addWidget(self.showBrowser) self.showBrowser.connect('clicked()', self.detailsPopup.open) # connect to the main window's dicom button mw = slicer.util.mainWindow() try: action = slicer.util.findChildren(mw,name='LoadDICOMAction')[0] action.connect('triggered()',self.detailsPopup.open) except IndexError: print('Could not connect to the main window DICOM button') # connect to our menu file entry so it raises the browser fileMenu = slicer.util.lookupTopLevelWidget('FileMenu') if fileMenu: for action in fileMenu.actions(): if action.text == 'DICOM': action.connect('triggered()',self.detailsPopup.open) # make the tables view a bit bigger self.tables.setMinimumHeight(250) if hasattr(slicer, 'dicomListener'): slicer.dicomListener.fileToBeAddedCallback = self.onListenerToAddFile slicer.dicomListener.fileAddedCallback = self.onListenerAddedFile # TODO: populate context menu self.contextMenu = qt.QMenu(self.tables) self.deleteAction = qt.QAction("Delete", self.contextMenu) self.contextMenu.addAction(self.deleteAction) self.deleteAction.enabled = False self.contextMenu.connect('triggered(QAction*)', self.onContextMenuTriggered) slicer.dicomDatabase.connect('databaseChanged()', self.onDatabaseChanged) self.dicomBrowser.connect('databaseDirectoryChanged(QString)', self.onDatabaseDirectoryChanged) self.tables.connect('seriesSelectionChanged(QStringList)', self.onSeriesSelected) self.tables.setContextMenuPolicy(3) self.tables.connect('customContextMenuRequested(QPoint)', self.onTreeContextMenuRequested) # enable to the Send button of the app widget and take it over # for our purposes - TODO: fix this to enable it at the ctkDICOM level self.sendButton = slicer.util.findChildren(self.dicomBrowser, text='Send')[0] self.sendButton.enabled = False self.sendButton.connect('triggered()', self.onSendClicked) # the recent activity frame self.activityFrame = ctk.ctkCollapsibleButton(self.parent) 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.widget) self.requestUpdateRecentActivity() # Add spacer to layout self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) # # input volume selector # self.inputSelector = slicer.qMRMLNodeComboBox() self.inputSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.inputSelector.selectNodeUponCreation = True self.inputSelector.addEnabled = False self.inputSelector.removeEnabled = False self.inputSelector.noneEnabled = False self.inputSelector.showHidden = False self.inputSelector.showChildNodeTypes = False self.inputSelector.setMRMLScene(slicer.mrmlScene) self.inputSelector.setToolTip("Pick the input to the algorithm.") parametersFormLayout.addRow("Input Volume: ", self.inputSelector) # # output volume selector # self.outputSelector = slicer.qMRMLNodeComboBox() self.outputSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.outputSelector.selectNodeUponCreation = True self.outputSelector.addEnabled = True self.outputSelector.removeEnabled = True self.outputSelector.noneEnabled = True self.outputSelector.showHidden = False self.outputSelector.showChildNodeTypes = False self.outputSelector.setMRMLScene(slicer.mrmlScene) self.outputSelector.setToolTip("Pick the output to the algorithm.") parametersFormLayout.addRow("Output Volume: ", self.outputSelector) # # threshold value # self.imageThresholdSliderWidget = ctk.ctkSliderWidget() self.imageThresholdSliderWidget.singleStep = 0.1 self.imageThresholdSliderWidget.minimum = -100 self.imageThresholdSliderWidget.maximum = 100 self.imageThresholdSliderWidget.value = 0.5 self.imageThresholdSliderWidget.setToolTip( "Set threshold value for computing the output image. Voxels that have intensities lower than this value will set to zero." ) parametersFormLayout.addRow("Image threshold", self.imageThresholdSliderWidget) # # check box to trigger taking screen shots for later use in tutorials # self.enableScreenshotsFlagCheckBox = qt.QCheckBox() self.enableScreenshotsFlagCheckBox.checked = 0 self.enableScreenshotsFlagCheckBox.setToolTip( "If checked, take screen shots for tutorials. Use Save Data to write them to disk." ) parametersFormLayout.addRow("Enable Screenshots", self.enableScreenshotsFlagCheckBox) # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Run the algorithm." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) self.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) # Add vertical spacer self.layout.addStretch(1) # Refresh Apply button state self.onSelect()
def setup(self): # Instantiate and connect widgets ... if self.developerMode: # # Reload and Test area # reloadCollapsibleButton = ctk.ctkCollapsibleButton() reloadCollapsibleButton.text = "Reload && Test" self.layout.addWidget(reloadCollapsibleButton) reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton) # reload button # (use this during development, but remove it when delivering # your module to users) self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "VolumeProbe Reload" reloadFormLayout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # reload and test button # (use this during development, but remove it when delivering # your module to users) self.reloadAndTestButton = qt.QPushButton("Reload and Test All") self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests." reloadFormLayout.addWidget(self.reloadAndTestButton) self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest) # reload and run specific tests scenarios = ("Three Volume", "View Watcher", "ROIManager",) for scenario in scenarios: button = qt.QPushButton("Reload and Test %s" % scenario) self.reloadAndTestButton.toolTip = "Reload this module and then run the %s self test." % scenario reloadFormLayout.addWidget(button) button.connect('clicked()', lambda s=scenario: self.onReloadAndTest(scenario=s)) # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) """ # # target volume selector # self.inputSelector = slicer.qMRMLNodeComboBox() self.inputSelector.nodeTypes = ( ("vtkMRMLVolumeNode"), "" ) self.inputSelector.selectNodeUponCreation = True self.inputSelector.addEnabled = False self.inputSelector.removeEnabled = False self.inputSelector.noneEnabled = False self.inputSelector.showHidden = False self.inputSelector.showChildNodeTypes = True self.inputSelector.setMRMLScene( slicer.mrmlScene ) self.inputSelector.setToolTip( "Pick the input to the algorithm." ) parametersFormLayout.addRow("Target Volume: ", self.inputSelector) """ # # Add ROI # self.drawROICheck = qt.QCheckBox() parametersFormLayout.addRow("Draw ROI", self.drawROICheck) self.drawROICheck.connect("toggled(bool)", self.onDrawROIToggled) self.ROIRadiusSlider = ctk.ctkSliderWidget() #self.ROIRadiusSlider.setMinimum(1) #self.ROIRadiusSlider.setMaximum(100) self.ROIRadiusSlider.setValue(self.ROIRadius) parametersFormLayout.addRow("ROI Radius", self.ROIRadiusSlider) self.ROIRadiusSlider.connect("valueChanged(double)", self.onROIRadiusChanged) # # Add Histogram self.numBins = qt.QSpinBox() self.numBins.setRange(0, 200) self.numBins.setEnabled(1) self.numBins.setValue(20) parametersFormLayout.addRow("Number of Bins", self.numBins) self.histogramArray = vtk.vtkDoubleArray() self.histogramArray.SetNumberOfComponents(1) self.histogramArray.SetNumberOfTuples(0) self.histogram = ctk.ctkVTKHistogram() self.histogram.setDataArray(self.histogramArray) self.histogram.numberOfBins = self.numBins.value self.histogramView = ctk.ctkTransferFunctionView() self.histogramItem = ctk.ctkTransferFunctionBarsItem(self.histogram) self.histogramItem.barWidth = 0.7 self.histogramView.scene().addItem(self.histogramItem) parametersFormLayout.addRow("Histogram", self.histogramView) self.histogramView.show() self.minField = qt.QSpinBox() self.minField.setRange(-100000, 100000) self.minField.setEnabled(0) parametersFormLayout.addRow("Min Value", self.minField) self.maxField = qt.QSpinBox() self.maxField.setRange(-100000, 100000) self.maxField.setEnabled(0) parametersFormLayout.addRow("Max Value", self.maxField) self.meanField = qt.QSpinBox() self.meanField.setRange(-100000, 100000) self.meanField.setEnabled(0) parametersFormLayout.addRow("Mean Value", self.meanField) self.medianField = qt.QSpinBox() self.medianField.setRange(-100000, 100000) self.medianField.setEnabled(0) parametersFormLayout.addRow("Median Value", self.medianField) self.stdField = qt.QSpinBox() self.stdField.setRange(-100000, 100000) self.stdField.setEnabled(0) parametersFormLayout.addRow("STD Value", self.stdField) # Add vertical spacer self.layout.addStretch(1)
def createUserInterface( self ): ''' ''' # self.buttonBoxHints = self.ButtonBoxHidden self.__layout = self.__parent.createUserInterface() # find all metrics in the plugins directory. The assumption is that all # metrics are named as ChangeTracker*Metric allModules = dir(slicer.moduleNames) changeTrackerMetrics = [] for m in allModules: if m.endswith('Metric'): changeTrackerMetrics.append(m) print 'Metrics discovered: ', changeTrackerMetrics # if len(changeTrackerMetrics) == 0: # report error -- should this be done in __init__ ? self.__metricCheckboxList = {} self.__basicFrame = ctk.ctkCollapsibleButton() self.__basicFrame.text = "Basic settings" self.__basicFrame.collapsed = 0 basicFrameLayout = qt.QFormLayout(self.__basicFrame) self.__layout.addRow(self.__basicFrame) self.__advancedFrame = ctk.ctkCollapsibleButton() self.__advancedFrame.text = "Advanced settings" self.__advancedFrame.collapsed = 1 boxLayout = qt.QVBoxLayout(self.__advancedFrame) self.__layout.addRow(self.__advancedFrame) self.__metricsFrame = ctk.ctkCollapsibleButton() self.__metricsFrame.text = "Change Detection Metrics" self.__metricsFrame.collapsed = 0 metricsFrameLayout = qt.QVBoxLayout(self.__metricsFrame) boxLayout.addWidget(self.__metricsFrame) self.__registrationFrame = ctk.ctkCollapsibleButton() self.__registrationFrame.text = "Registration" self.__registrationFrame.collapsed = 0 registrationFrameLayout = qt.QFormLayout(self.__registrationFrame) boxLayout.addWidget(self.__registrationFrame) self.__metricsTabs = qt.QTabWidget() metricsFrameLayout.addWidget(self.__metricsTabs) # TODO: error checking! for m in changeTrackerMetrics: pluginName = m moduleManager = slicer.app.moduleManager() plugin = moduleManager.module(pluginName) label = qt.QLabel(plugin.title) checkbox = qt.QCheckBox() self.__metricCheckboxList[checkbox] = pluginName # initialize basic frame basicFrameLayout.addRow(label, checkbox) # initialize advanced frame metricGui = slicer.util.getModuleGui(pluginName) parametersWidget = Helper.findChildren(metricGui, text='Parameters')[0] if parametersWidget != None: metricWidget = qt.QWidget() metricLayout = qt.QFormLayout(metricWidget) metricLayout.addRow(parametersWidget) self.__metricsTabs.addTab(metricWidget, pluginName) self.__transformSelector = slicer.qMRMLNodeComboBox() self.__transformSelector.toolTip = "Transform aligning the follow-up scan with the baseline" self.__transformSelector.nodeTypes = ['vtkMRMLLinearTransformNode'] self.__transformSelector.noneEnabled = 1 self.__transformSelector.setMRMLScene(slicer.mrmlScene) transformSelectorLabel = qt.QLabel('Transform: ') registrationFrameLayout.addRow(transformSelectorLabel, self.__transformSelector)
def setup(self): # check if the SlicerVmtk module is installed properly # self.__vmtkInstalled = SlicerVmtkCommonLib.Helper.CheckIfVmtkIsInstalled() # Helper.Debug("VMTK found: " + self.__vmtkInstalled) # # the I/O panel # ioCollapsibleButton = ctk.ctkCollapsibleButton() ioCollapsibleButton.text = "Input/Output" self.layout.addWidget(ioCollapsibleButton) ioFormLayout = qt.QFormLayout(ioCollapsibleButton) # inputVolume selector self.__inputVolumeNodeSelector = slicer.qMRMLNodeComboBox() self.__inputVolumeNodeSelector.objectName = 'inputVolumeNodeSelector' self.__inputVolumeNodeSelector.toolTip = "Select the input volume. This should always be the original image and not a vesselness image, if possible." self.__inputVolumeNodeSelector.nodeTypes = ['vtkMRMLScalarVolumeNode'] self.__inputVolumeNodeSelector.noneEnabled = False self.__inputVolumeNodeSelector.addEnabled = False self.__inputVolumeNodeSelector.removeEnabled = False self.__inputVolumeNodeSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", "0") ioFormLayout.addRow("Input Volume:", self.__inputVolumeNodeSelector) self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.__inputVolumeNodeSelector, 'setMRMLScene(vtkMRMLScene*)') self.__inputVolumeNodeSelector.connect( 'currentNodeChanged(vtkMRMLNode*)', self.onInputVolumeChanged) self.__inputVolumeNodeSelector.connect('nodeActivated(vtkMRMLNode*)', self.onInputVolumeChanged) # seed selector self.__seedFiducialsNodeSelector = slicer.qMRMLNodeComboBox() self.__seedFiducialsNodeSelector.objectName = 'seedFiducialsNodeSelector' self.__seedFiducialsNodeSelector.toolTip = "Select a hierarchy containing the fiducials to use as Seeds." self.__seedFiducialsNodeSelector.nodeTypes = [ 'vtkMRMLAnnotationHierarchyNode' ] self.__seedFiducialsNodeSelector.baseName = "Seeds" self.__seedFiducialsNodeSelector.noneEnabled = False self.__seedFiducialsNodeSelector.addEnabled = False self.__seedFiducialsNodeSelector.removeEnabled = False ioFormLayout.addRow("Seeds:", self.__seedFiducialsNodeSelector) self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.__seedFiducialsNodeSelector, 'setMRMLScene(vtkMRMLScene*)') self.__ioAdvancedToggle = qt.QCheckBox("Show Advanced I/O Properties") self.__ioAdvancedToggle.setChecked(False) ioFormLayout.addRow(self.__ioAdvancedToggle) # # I/O advanced panel # self.__ioAdvancedPanel = qt.QFrame(ioCollapsibleButton) self.__ioAdvancedPanel.hide() self.__ioAdvancedPanel.setFrameStyle(6) ioFormLayout.addRow(self.__ioAdvancedPanel) self.__ioAdvancedToggle.connect("clicked()", self.onIOAdvancedToggle) ioAdvancedFormLayout = qt.QFormLayout(self.__ioAdvancedPanel) # inputVolume selector self.__vesselnessVolumeNodeSelector = slicer.qMRMLNodeComboBox() self.__vesselnessVolumeNodeSelector.objectName = 'vesselnessVolumeNodeSelector' self.__vesselnessVolumeNodeSelector.toolTip = "Select the input vesselness volume. This is optional input." self.__vesselnessVolumeNodeSelector.nodeTypes = [ 'vtkMRMLScalarVolumeNode' ] self.__vesselnessVolumeNodeSelector.noneEnabled = True self.__vesselnessVolumeNodeSelector.addEnabled = False self.__vesselnessVolumeNodeSelector.removeEnabled = False self.__vesselnessVolumeNodeSelector.addAttribute( "vtkMRMLScalarVolumeNode", "LabelMap", "0") ioAdvancedFormLayout.addRow("Vesselness Volume:", self.__vesselnessVolumeNodeSelector) self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.__vesselnessVolumeNodeSelector, 'setMRMLScene(vtkMRMLScene*)') self.__vesselnessVolumeNodeSelector.setCurrentNode(None) # stopper selector self.__stopperFiducialsNodeSelector = slicer.qMRMLNodeComboBox() self.__stopperFiducialsNodeSelector.objectName = 'stopperFiducialsNodeSelector' self.__stopperFiducialsNodeSelector.toolTip = "Select a hierarchy containing the fiducials to use as Stoppers. Whenever one stopper is reached, the segmentation stops." self.__stopperFiducialsNodeSelector.nodeTypes = [ 'vtkMRMLAnnotationHierarchyNode' ] self.__stopperFiducialsNodeSelector.baseName = "Stoppers" self.__stopperFiducialsNodeSelector.noneEnabled = False self.__stopperFiducialsNodeSelector.addEnabled = True self.__stopperFiducialsNodeSelector.removeEnabled = False ioAdvancedFormLayout.addRow("Stoppers:", self.__stopperFiducialsNodeSelector) self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.__stopperFiducialsNodeSelector, 'setMRMLScene(vtkMRMLScene*)') # outputVolume selector self.__outputVolumeNodeSelector = slicer.qMRMLNodeComboBox() self.__outputVolumeNodeSelector.toolTip = "Select the output labelmap." self.__outputVolumeNodeSelector.nodeTypes = ['vtkMRMLScalarVolumeNode'] self.__outputVolumeNodeSelector.baseName = "LevelSetSegmentation" self.__outputVolumeNodeSelector.noneEnabled = False self.__outputVolumeNodeSelector.addEnabled = True self.__outputVolumeNodeSelector.selectNodeUponCreation = True self.__outputVolumeNodeSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", "1") self.__outputVolumeNodeSelector.removeEnabled = True ioAdvancedFormLayout.addRow("Output Labelmap:", self.__outputVolumeNodeSelector) self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.__outputVolumeNodeSelector, 'setMRMLScene(vtkMRMLScene*)') # outputModel selector self.__outputModelNodeSelector = slicer.qMRMLNodeComboBox() self.__outputModelNodeSelector.objectName = 'outputModelNodeSelector' self.__outputModelNodeSelector.toolTip = "Select the output model." self.__outputModelNodeSelector.nodeTypes = ['vtkMRMLModelNode'] self.__outputModelNodeSelector.baseName = "LevelSetSegmentationModel" self.__outputModelNodeSelector.hideChildNodeTypes = [ 'vtkMRMLAnnotationNode' ] # hide all annotation nodes self.__outputModelNodeSelector.noneEnabled = False self.__outputModelNodeSelector.addEnabled = True self.__outputModelNodeSelector.selectNodeUponCreation = True self.__outputModelNodeSelector.removeEnabled = True ioAdvancedFormLayout.addRow("Output Model:", self.__outputModelNodeSelector) self.parent.connect('mrmlSceneChanged(vtkMRMLScene*)', self.__outputModelNodeSelector, 'setMRMLScene(vtkMRMLScene*)') # # the segmentation panel # segmentationCollapsibleButton = ctk.ctkCollapsibleButton() segmentationCollapsibleButton.text = "Segmentation" self.layout.addWidget(segmentationCollapsibleButton) segmentationFormLayout = qt.QFormLayout(segmentationCollapsibleButton) # Threshold slider thresholdLabel = qt.QLabel() thresholdLabel.text = "Thresholding" + SlicerVmtkCommonLib.Helper.CreateSpace( 7) thresholdLabel.toolTip = "Choose the intensity range to segment." thresholdLabel.setAlignment(4) segmentationFormLayout.addRow(thresholdLabel) self.__thresholdSlider = slicer.qMRMLRangeWidget() segmentationFormLayout.addRow(self.__thresholdSlider) self.__thresholdSlider.connect('valuesChanged(double,double)', self.onThresholdSliderChanged) self.__segmentationAdvancedToggle = qt.QCheckBox( "Show Advanced Segmentation Properties") self.__segmentationAdvancedToggle.setChecked(False) segmentationFormLayout.addRow(self.__segmentationAdvancedToggle) # # segmentation advanced panel # self.__segmentationAdvancedPanel = qt.QFrame( segmentationCollapsibleButton) self.__segmentationAdvancedPanel.hide() self.__segmentationAdvancedPanel.setFrameStyle(6) segmentationFormLayout.addRow(self.__segmentationAdvancedPanel) self.__segmentationAdvancedToggle.connect( "clicked()", self.onSegmentationAdvancedToggle) segmentationAdvancedFormLayout = qt.QFormLayout( self.__segmentationAdvancedPanel) # inflation slider inflationLabel = qt.QLabel() inflationLabel.text = "less inflation <-> more inflation" + SlicerVmtkCommonLib.Helper.CreateSpace( 14) inflationLabel.setAlignment(4) inflationLabel.toolTip = "Define how fast the segmentation expands." segmentationAdvancedFormLayout.addRow(inflationLabel) self.__inflationSlider = ctk.ctkSliderWidget() self.__inflationSlider.decimals = 0 self.__inflationSlider.minimum = -100 self.__inflationSlider.maximum = 100 self.__inflationSlider.singleStep = 10 self.__inflationSlider.toolTip = inflationLabel.toolTip segmentationAdvancedFormLayout.addRow(self.__inflationSlider) # curvature slider curvatureLabel = qt.QLabel() curvatureLabel.text = "less curvature <-> more curvature" + SlicerVmtkCommonLib.Helper.CreateSpace( 14) curvatureLabel.setAlignment(4) curvatureLabel.toolTip = "Choose a high curvature to generate a smooth segmentation." segmentationAdvancedFormLayout.addRow(curvatureLabel) self.__curvatureSlider = ctk.ctkSliderWidget() self.__curvatureSlider.decimals = 0 self.__curvatureSlider.minimum = -100 self.__curvatureSlider.maximum = 100 self.__curvatureSlider.singleStep = 10 self.__curvatureSlider.toolTip = curvatureLabel.toolTip segmentationAdvancedFormLayout.addRow(self.__curvatureSlider) # attraction slider attractionLabel = qt.QLabel() attractionLabel.text = "less attraction to gradient <-> more attraction to gradient" + SlicerVmtkCommonLib.Helper.CreateSpace( 14) attractionLabel.setAlignment(4) attractionLabel.toolTip = "Configure how the segmentation travels towards gradient ridges (vessel lumen wall)." segmentationAdvancedFormLayout.addRow(attractionLabel) self.__attractionSlider = ctk.ctkSliderWidget() self.__attractionSlider.decimals = 0 self.__attractionSlider.minimum = -100 self.__attractionSlider.maximum = 100 self.__attractionSlider.singleStep = 10 self.__attractionSlider.toolTip = attractionLabel.toolTip segmentationAdvancedFormLayout.addRow(self.__attractionSlider) # iteration spinbox self.__iterationSpinBox = qt.QSpinBox() self.__iterationSpinBox.minimum = 0 self.__iterationSpinBox.maximum = 5000 self.__iterationSpinBox.singleStep = 10 self.__iterationSpinBox.toolTip = "Choose the number of evolution iterations." segmentationAdvancedFormLayout.addRow( SlicerVmtkCommonLib.Helper.CreateSpace(100) + "Iterations:", self.__iterationSpinBox) # # Reset, preview and apply buttons # self.__buttonBox = qt.QDialogButtonBox() self.__resetButton = self.__buttonBox.addButton( self.__buttonBox.RestoreDefaults) self.__resetButton.toolTip = "Click to reset all input elements to default." self.__previewButton = self.__buttonBox.addButton( self.__buttonBox.Discard) self.__previewButton.setIcon(qt.QIcon()) self.__previewButton.text = "Preview.." self.__previewButton.toolTip = "Click to refresh the preview." self.__startButton = self.__buttonBox.addButton(self.__buttonBox.Apply) self.__startButton.setIcon(qt.QIcon()) self.__startButton.text = "Start!" self.__startButton.enabled = False self.__startButton.toolTip = "Click to start the filtering." self.layout.addWidget(self.__buttonBox) self.__resetButton.connect("clicked()", self.restoreDefaults) self.__previewButton.connect("clicked()", self.onRefreshButtonClicked) self.__startButton.connect("clicked()", self.onStartButtonClicked) # be ready for events self.__updating = 0 # set default values self.restoreDefaults() # compress the layout self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) print("-------Mesh Statistic Widget Setup-------") # ------------------------------------------------------------------------------------- self.modelList = list() self.fieldList = list() self.ROIList = list() self.ROIDict = dict() # Key = Name of ROI # Value = Dictionary of Fields (key = Name of Field # Value = dictionary of shapes # key = name of shapes # value = Statistics store() self.logic = MeshStatisticsLogic(self) # ---------------------------------------------------------------- # # ---------------- Definition of the UI interface ---------------- # # ---------------------------------------------------------------- # # ------------ Loading of the .ui file ---------- # modulePath = os.path.dirname(slicer.util.modulePath(self.moduleName)) path = os.path.join(modulePath, 'Resources', 'UI', '%s.ui' % self.moduleName) self.layout = self.parent.layout() self.widget = slicer.util.loadUI(path) self.layout.addWidget(self.widget) # ------------------------------------------------------------------------------------ # SHAPES INPUT # ------------------------------------------------------------------------------------ self.inputComboBox = self.logic.get("inputComboBox") self.inputComboBox.setMRMLScene(slicer.mrmlScene) self.inputComboBox.connect('checkedNodesChanged()', self.onInputComboBoxCheckedNodesChanged) # ------------------------------------------------------------------------------------ # ROI TABLE # ------------------------------------------------------------------------------------ self.ROIComboBox = self.logic.get("ROIComboBox") self.ROICheckBox = self.logic.get("ROICheckBox") self.ROICheckBox.connect('stateChanged(int)', self.onROICheckBoxStateChanged) # ------------------------------------------------------------------------------------ # FIELD TABLE # ------------------------------------------------------------------------------------ self.tableField = self.logic.get("tableField") self.tableField.setColumnCount(2) self.tableField.setMinimumHeight(250) self.tableField.setHorizontalHeaderLabels([' ', ' Field Name ']) self.tableField.setColumnWidth(0, 20) self.tableField.setColumnWidth(1, 260) self.tableField.setSizePolicy(qt.QSizePolicy().Expanding, qt.QSizePolicy().Expanding) # ------------------------------------------------------------------------------------ # RUN # ------------------------------------------------------------------------------------ self.runButton = self.logic.get("runButton") self.runButton.connect('clicked()', self.onRunButton) # ------------------------------------------------------------------------------------ # Statistics Table - Export # ------------------------------------------------------------------------------------ self.mainLayout = self.logic.get("mainLayout") self.tabROI = qt.QTabWidget() self.tabROI.setTabPosition(0) self.tabROI.adjustSize() # ---------------------------- Directory - Export Button ----------------------------- self.directoryExport = ctk.ctkDirectoryButton() self.exportCheckBox = qt.QCheckBox('Separate Files') self.exportCheckBox.setChecked(True) self.exportButton = qt.QPushButton(' Export ') self.exportButton.enabled = True self.exportPointValueCheckBox = qt.QCheckBox('Export Value on Each Point') self.exportLayout = qt.QVBoxLayout() self.directoryAndExportLayout = qt.QHBoxLayout() self.directoryAndExportLayout.addWidget(self.directoryExport) self.directoryAndExportLayout.addWidget(self.exportCheckBox) self.directoryAndExportLayout.addWidget(self.exportPointValueCheckBox) self.exportButtonsLayout = qt.QHBoxLayout() self.exportButtonsLayout.addWidget(self.exportButton) self.exportLayout.addLayout(self.directoryAndExportLayout) self.exportLayout.addLayout(self.exportButtonsLayout) self.layout.addStretch(1) self.logic.updateInterface(self.tableField, self.ROIComboBox, self.ROIList, self.modelList, self.mainLayout) # ------------------------------------------------------------------------------------ # OBSERVERS # ------------------------------------------------------------------------------------ slicer.mrmlScene.AddObserver(slicer.mrmlScene.EndCloseEvent, self.onCloseScene)
def updateInterface(self, tableField, ROIComboBox, ROIList, modelList, layout): tableField.clearContents() tableField.setRowCount(0) ROIComboBox.clear() ROIComboBox.addItem('Entire Model') del ROIList[:] ROIList.append('Entire Model') tableFieldNumRows = 0 expression = '_ROI' if tableField.rowCount == 0: tableField.setRowCount(1) tableField.setSpan(0,0,1,2) label = qt.QLabel(' Please select at least a model! ') label.setStyleSheet(' QLabel{ qproperty-alignment: AlignCenter; }') tableField.setCellWidget(tableFieldNumRows, 0, label) if modelList: tableField.setSpan(0,0,1,1) numberOfArrayList = list() for model in modelList: numberOfArrayList.append(model.GetPolyData().GetPointData().GetNumberOfArrays()) # set the model with the higher number of fields as reference modelOfReference = modelList[numberOfArrayList.index(max(numberOfArrayList))] PointDataOfReference = modelOfReference.GetPolyData().GetPointData() numOfArrayOfReference = PointDataOfReference.GetNumberOfArrays() fieldInCommon = list() fieldNotInCommon = [] fieldNameOfRefList = list() fieldModel = list() del fieldNameOfRefList[:] for i in range(0, numOfArrayOfReference): if PointDataOfReference.GetArray(i).GetNumberOfComponents() == 1: fieldNameOfRefList.append(PointDataOfReference.GetArray(i).GetName()) fieldInCommon.append(PointDataOfReference.GetArray(i).GetName()) if modelList.__len__() > 1: for model in modelList: del fieldModel[:] if model.GetID() != modelOfReference.GetID(): numOfArray = model.GetPolyData().GetPointData().GetNumberOfArrays() for i in range(0, numOfArray): if model.GetPolyData().GetPointData().GetArray(i).GetNumberOfComponents() == 1: fieldModel.append(model.GetPolyData().GetPointData().GetArray(i).GetName()) fieldInCommon, tempFieldNotInCommon = self.compareList(fieldInCommon, fieldModel) fieldNotInCommon = fieldNotInCommon + tempFieldNotInCommon for arrayName in set(fieldInCommon): if not re.search(expression, arrayName): tableFieldNumRows += 1 tableField.setMinimumHeight(tableFieldNumRows*35) tableField.setRowCount(tableFieldNumRows) tableField.setCellWidget(tableFieldNumRows - 1, 0, qt.QCheckBox()) label = qt.QLabel(arrayName) label.setStyleSheet(' QLabel{qproperty-alignment: AlignVCenter | AlignLeft; }') tableField.setCellWidget(tableFieldNumRows - 1, 1, label) else: ROIComboBox.addItem(arrayName) ROIList.append(arrayName) for arrayName in set(fieldNotInCommon): if not re.search(expression, arrayName): tableFieldNumRows += 1 tableField.setMinimumHeight(tableFieldNumRows*35) tableField.setRowCount(tableFieldNumRows) label = qt.QLabel(arrayName) label.setStyleSheet(' QLabel{ font-style:oblique; text-decoration:line-through; }') tableField.setCellWidget(tableFieldNumRows - 1, 1, label ) layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) self.inputDirSelector = ctk.ctkPathLineEdit() self.inputDirSelector.filters = ctk.ctkPathLineEdit.Dirs self.inputDirSelector.settingKey = 'Philips4dUsDicomPatcherInputDir' parametersFormLayout.addRow("Input DICOM directory:", self.inputDirSelector) self.outputDirSelector = ctk.ctkPathLineEdit() self.outputDirSelector.filters = ctk.ctkPathLineEdit.Dirs self.outputDirSelector.settingKey = 'Philips4dUsDicomPatcherOutputDir' parametersFormLayout.addRow("Output DICOM directory:", self.outputDirSelector) self.enableDicomOutputCheckBox = qt.QCheckBox() self.enableDicomOutputCheckBox.checked = True self.enableDicomOutputCheckBox.setToolTip( "If checked, patched 4D US DICOM files will be saved as DICOM files" ) parametersFormLayout.addRow("Export to DICOM files", self.enableDicomOutputCheckBox) self.anonymizeDicomCheckBox = qt.QCheckBox() self.anonymizeDicomCheckBox.checked = False self.anonymizeDicomCheckBox.setToolTip( "If checked, then patient identifiable information will be removed from the patched DICOM files" ) parametersFormLayout.addRow(" Anonymize DICOM files", self.anonymizeDicomCheckBox) self.enableNrrdOutputCheckBox = qt.QCheckBox() self.enableNrrdOutputCheckBox.checked = False self.enableNrrdOutputCheckBox.setToolTip( "If checked, 4D US DICOM files will be saved as NRRD files") parametersFormLayout.addRow("Export to NRRD files", self.enableNrrdOutputCheckBox) # # Patch Button # self.patchButton = qt.QPushButton("Patch") self.patchButton.toolTip = "Fix and optionally anonymize DICOM files" parametersFormLayout.addRow(self.patchButton) # connections self.patchButton.connect('clicked(bool)', self.onPatchButton) self.statusLabel = qt.QPlainTextEdit() self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse) parametersFormLayout.addRow(self.statusLabel) # Add vertical spacer self.layout.addStretch(1) self.logic = Philips4dUsDicomPatcherLogic() self.logic.logCallback = self.addLog
def setup(self): # Instantiate and connect widgets ... # # Reload and Test area # reloadCollapsibleButton = ctk.ctkCollapsibleButton() reloadCollapsibleButton.text = "Reload && Test" self.layout.addWidget(reloadCollapsibleButton) reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton) # reload button # (use this during development, but remove it when delivering # your module to users) self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "ScriptedLoadableModuleTemplate Reload" reloadFormLayout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # reload and test button # (use this during development, but remove it when delivering # your module to users) self.reloadAndTestButton = qt.QPushButton("Reload and Test") self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests." reloadFormLayout.addWidget(self.reloadAndTestButton) self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest) # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) # # input volume selector # self.inputSelector = slicer.qMRMLNodeComboBox() self.inputSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.inputSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", 0) self.inputSelector.selectNodeUponCreation = True self.inputSelector.addEnabled = False self.inputSelector.removeEnabled = False self.inputSelector.noneEnabled = False self.inputSelector.showHidden = False self.inputSelector.showChildNodeTypes = False self.inputSelector.setMRMLScene(slicer.mrmlScene) self.inputSelector.setToolTip("Pick the input to the algorithm.") parametersFormLayout.addRow("Input Volume: ", self.inputSelector) # # output volume selector # self.outputSelector = slicer.qMRMLNodeComboBox() self.outputSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.outputSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", 0) self.outputSelector.selectNodeUponCreation = False self.outputSelector.addEnabled = True self.outputSelector.removeEnabled = True self.outputSelector.noneEnabled = False self.outputSelector.showHidden = False self.outputSelector.showChildNodeTypes = False self.outputSelector.setMRMLScene(slicer.mrmlScene) self.outputSelector.setToolTip("Pick the output to the algorithm.") parametersFormLayout.addRow("Output Volume: ", self.outputSelector) # # check box to trigger taking screen shots for later use in tutorials # self.enableScreenshotsFlagCheckBox = qt.QCheckBox() self.enableScreenshotsFlagCheckBox.checked = 0 self.enableScreenshotsFlagCheckBox.setToolTip( "If checked, take screen shots for tutorials. Use Save Data to write them to disk." ) parametersFormLayout.addRow("Enable Screenshots", self.enableScreenshotsFlagCheckBox) # # scale factor for screen shots # self.screenshotScaleFactorSliderWidget = ctk.ctkSliderWidget() self.screenshotScaleFactorSliderWidget.singleStep = 1.0 self.screenshotScaleFactorSliderWidget.minimum = 1.0 self.screenshotScaleFactorSliderWidget.maximum = 50.0 self.screenshotScaleFactorSliderWidget.value = 1.0 self.screenshotScaleFactorSliderWidget.setToolTip( "Set scale factor for the screen shots.") parametersFormLayout.addRow("Screenshot scale factor", self.screenshotScaleFactorSliderWidget) # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Run the algorithm." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.inputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) self.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) # Add vertical spacer self.layout.addStretch(1)
def create(self, json): if not self.parent: raise "no parent" parametersFormLayout = self.parent.layout() # You can't use exec in a function that has a subfunction, unless you specify a context. exec('self.filter = sitk.{0}()'.format( json["name"])) in globals(), locals() self.prerun_callbacks = [] self.inputs = [] self.outputLabelMap = False # # input volume selectors # if "inputs" in json: # have named inputs n = 0 for input in json["inputs"]: w = self.createInputWidget(n, noneEnabled=("optional" in input and input["optional"])) name = "Input Volume: " if "name" in input: name = "Input {0}: ".format(input["name"]) name = name.replace("Image", "Volume") print "adding {1}: {0}".format(name, n) inputSelectorLabel = qt.QLabel(name) self.widgets.append(inputSelectorLabel) # add to layout after connection parametersFormLayout.addRow(inputSelectorLabel, w) self.inputs.append(w.currentNode()) n += 1 if "number_of_inputs" in json and json["number_of_inputs"] != 0: import sys sys.stderr.write( "Expected \"number_of_inputs\" to be 0 not {0}!". format(json["number_of_inputs"])) else: for n in range(json["number_of_inputs"]): w = self.createInputWidget(n) inputSelectorLabel = qt.QLabel("Input Volume: ") self.widgets.append(inputSelectorLabel) # add to layout after connection parametersFormLayout.addRow(inputSelectorLabel, w) self.inputs.append(w.currentNode()) #end for each input if json["template_code_filename"] == "KernelImageFilter": w = self.createVectorWidget("KernelRadius", "std::vector<uint32_t>") self.widgets.append(w) self.addWidgetWithToolTipAndLabel( w, { "briefdescriptionSet": "Radius of structuring element", "name": "KernelRadius" }) labels = ["Annulus", "Box", "Ball", "Cross"] values = [ "sitk.sitkAnnulus", "sitk.sitkBox", "sitk.sitkBall", "sitk.sitkCross" ] w = self.createEnumWidget("KernelType", labels, values) self.addWidgetWithToolTipAndLabel( w, { "briefdescriptionSet": "Structuring element", "name": "Kernel Type" }) elif json["template_code_filename"] == "RegionGrowingImageFilter"\ or json["template_code_filename"] == "FastMarchingImageFilter": name = "SeedList" if (json["template_code_filename"] == "FastMarchingImageFilter"): name = "TrialPoints" fiducialSelector = slicer.qMRMLNodeComboBox() self.widgets.append(fiducialSelector) fiducialSelector.nodeTypes = ("vtkMRMLMarkupsFiducialNode", "vtkMRMLAnnotationHierarchyNode") fiducialSelector.addAttribute("vtkMRMLAnnotationHierarchyNode", "MainChildType", "vtkMRMLAnnotationFiducialNode") fiducialSelector.selectNodeUponCreation = True fiducialSelector.addEnabled = True fiducialSelector.removeEnabled = False fiducialSelector.renameEnabled = True fiducialSelector.noneEnabled = False fiducialSelector.showHidden = False fiducialSelector.showChildNodeTypes = True fiducialSelector.setMRMLScene(slicer.mrmlScene) fiducialSelector.setToolTip( "Pick the Markups node for the seed list.") fiducialSelector.connect( "nodeActivated(vtkMRMLNode*)", lambda node, name=name: self.onFiducialListNode(name, node)) self.prerun_callbacks.append( lambda w=fiducialSelector, name=name: self.onFiducialListNode( name, w.currentNode())) fiducialSelectorLabel = qt.QLabel("{0}: ".format(name)) self.widgets.append(fiducialSelectorLabel) #todo set tool tip # add to layout after connection parametersFormLayout.addRow(fiducialSelectorLabel, fiducialSelector) # # Iterate over the members in the JSON to generate a GUI # for member in json["members"]: w = None if "type" in member: t = member["type"] if "dim_vec" in member and int(member["dim_vec"]): if member["itk_type"].endswith("IndexType") or member[ "itk_type"].endswith("PointType"): isPoint = member["itk_type"].endswith("PointType") fiducialSelector = slicer.qMRMLNodeComboBox() self.widgets.append(fiducialSelector) fiducialSelector.nodeTypes = ( "vtkMRMLMarkupsFiducialNode", "vtkMRMLAnnotationFiducialNode") fiducialSelector.selectNodeUponCreation = True fiducialSelector.addEnabled = False fiducialSelector.removeEnabled = False fiducialSelector.renameEnabled = True fiducialSelector.noneEnabled = False fiducialSelector.showHidden = False fiducialSelector.showChildNodeTypes = True fiducialSelector.setMRMLScene(slicer.mrmlScene) fiducialSelector.setToolTip( "Pick the Fiducial for the Point or Index") fiducialSelector.connect( "nodeActivated(vtkMRMLNode*)", lambda node, w=fiducialSelector, name=member["name"], isPt=isPoint: self.onFiducialNode(name, w, isPt)) self.prerun_callbacks.append( lambda w=fiducialSelector, name=member["name"], isPt= isPoint: self.onFiducialNode(name, w, isPt)) w1 = fiducialSelector fiducialSelectorLabel = qt.QLabel("{0}: ".format( member["name"])) self.widgets.append(fiducialSelectorLabel) icon = qt.QIcon(SimpleFilters.ICON_DIR + "Fiducials.png") toggle = qt.QPushButton(icon, "") toggle.setCheckable(True) toggle.toolTip = "Toggle Fiducial Selection" self.widgets.append(toggle) w2 = self.createVectorWidget(member["name"], t) hlayout = qt.QHBoxLayout() hlayout.addWidget(fiducialSelector) hlayout.setStretchFactor(fiducialSelector, 1) hlayout.addWidget(w2) hlayout.setStretchFactor(w2, 1) hlayout.addWidget(toggle) hlayout.setStretchFactor(toggle, 0) w1.hide() self.widgets.append(hlayout) toggle.connect("clicked(bool)", lambda checked, ptW=w2, fidW=w1: self. onToggledPointSelector(checked, ptW, fidW)) parametersFormLayout.addRow(fiducialSelectorLabel, hlayout) else: w = self.createVectorWidget(member["name"], t) elif "point_vec" in member: fiducialSelector = slicer.qMRMLNodeComboBox() self.widgets.append(fiducialSelector) fiducialSelector.nodeTypes = ("vtkMRMLMarkupsFiducialNode", "vtkMRMLAnnotationHierarchyNode") fiducialSelector.addAttribute("vtkMRMLAnnotationHierarchyNode", "MainChildType", "vtkMRMLAnnotationFiducialNode") fiducialSelector.selectNodeUponCreation = True fiducialSelector.addEnabled = True fiducialSelector.removeEnabled = False fiducialSelector.renameEnabled = True fiducialSelector.noneEnabled = False fiducialSelector.showHidden = False fiducialSelector.showChildNodeTypes = True fiducialSelector.setMRMLScene(slicer.mrmlScene) fiducialSelector.setToolTip( "Pick the Markups node for the point list.") fiducialSelector.connect("nodeActivated(vtkMRMLNode*)", lambda node, name=member["name"]: self .onFiducialListNode(name, node)) self.prerun_callbacks.append( lambda w=fiducialSelector, name=member["name"], : self. onFiducialListNode(name, w.currentNode())) w = fiducialSelector elif "enum" in member: w = self.createEnumWidget(member["name"], member["enum"]) elif member["name"].endswith("Direction") and "std::vector" in t: # This member name is use for direction cosine matrix for image sources. # We are going to ignore it pass elif t == "InterpolatorEnum": labels = [ "Nearest Neighbor", "Linear", "BSpline", "Gaussian", "Label Gaussian", "Hamming Windowed Sinc", "Cosine Windowed Sinc", "Welch Windowed Sinc", "Lanczos Windowed Sinc", "Blackman Windowed Sinc" ] values = [ "sitk.sitkNearestNeighbor", "sitk.sitkLinear", "sitk.sitkBSpline", "sitk.sitkGaussian", "sitk.sitkLabelGaussian", "sitk.sitkHammingWindowedSinc", "sitk.sitkCosineWindowedSinc", "sitk.sitkWelchWindowedSinc", "sitk.sitkLanczosWindowedSinc", "sitk.sitkBlackmanWindowedSinc" ] w = self.createEnumWidget(member["name"], labels, values) pass elif t == "PixelIDValueEnum": labels = [ "int8_t", "uint8_t", "int16_t", "uint16_t", "uint32_t", "int32_t", "float", "double" ] values = [ "sitk.sitkInt8", "sitk.sitkUInt8", "sitk.sitkInt16", "sitk.sitkUInt16", "sitk.sitkInt32", "sitk.sitkUInt32", "sitk.sitkFloat32", "sitk.sitkFloat64" ] w = self.createEnumWidget(member["name"], labels, values) elif t in ["double", "float"]: w = self.createDoubleWidget(member["name"]) elif t == "bool": w = self.createBoolWidget(member["name"]) elif t in [ "uint8_t", "int8_t", "uint16_t", "int16_t", "uint32_t", "int32_t", "uint64_t", "int64_t", "unsigned int", "int" ]: w = self.createIntWidget(member["name"], t) else: import sys sys.stderr.write( "Unknown member \"{0}\" of type \"{1}\"\n".format( member["name"], member["type"])) if w: self.addWidgetWithToolTipAndLabel(w, member) # end for each member # # output volume selector # outputSelectorLabel = qt.QLabel("Output Volume: ") self.widgets.append(outputSelectorLabel) self.outputSelector = slicer.qMRMLNodeComboBox() self.widgets.append(self.outputSelector) self.outputSelector.nodeTypes = [ "vtkMRMLScalarVolumeNode", "vtkMRMLLabelMapVolumeNode" ] self.outputSelector.selectNodeUponCreation = True self.outputSelector.addEnabled = True self.outputSelector.removeEnabled = False self.outputSelector.renameEnabled = True self.outputSelector.noneEnabled = False self.outputSelector.showHidden = False self.outputSelector.showChildNodeTypes = False self.outputSelector.baseName = json["name"] + " Output" self.outputSelector.setMRMLScene(slicer.mrmlScene) self.outputSelector.setToolTip("Pick the output to the algorithm.") self.outputSelector.connect("nodeActivated(vtkMRMLNode*)", lambda node: self.onOutputSelect(node)) # add to layout after connection parametersFormLayout.addRow(outputSelectorLabel, self.outputSelector) self.output = self.outputSelector.currentNode() # # LabelMap toggle # outputLabelMapLabel = qt.QLabel("LabelMap: ") self.widgets.append(outputLabelMapLabel) self.outputLabelMapBox = qt.QCheckBox() self.widgets.append(self.outputLabelMapBox) self.outputLabelMapBox.setToolTip("Output Volume is set as a labelmap") self.outputLabelMapBox.setChecked(self.outputLabelMap) self.outputLabelMapBox.setDisabled(True) self.outputLabelMapBox.connect( "stateChanged(int)", lambda val: self.onOutputLabelMapChanged(bool(val))) # add to layout after connection parametersFormLayout.addRow(outputLabelMapLabel, self.outputLabelMapBox)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) # # input fiducial list selector # fiducialWarningLabel = qt.QLabel( "Note: Parent transforms of fiducials are not used. Fiducials should be defined in the coordinate system that is being registered." ) fiducialWarningLabel.setWordWrap( True ) parametersFormLayout.addRow(fiducialWarningLabel) self.inputFiducialSelector = slicer.qMRMLNodeComboBox() self.inputFiducialSelector.nodeTypes = ( ("vtkMRMLMarkupsFiducialNode"), "" ) self.inputFiducialSelector.selectNodeUponCreation = True self.inputFiducialSelector.addEnabled = False self.inputFiducialSelector.removeEnabled = False self.inputFiducialSelector.noneEnabled = False self.inputFiducialSelector.showHidden = False self.inputFiducialSelector.showChildNodeTypes = False self.inputFiducialSelector.setMRMLScene( slicer.mrmlScene ) self.inputFiducialSelector.setToolTip( "Pick the input fiducial list for the algorithm." ) parametersFormLayout.addRow("Input fiducials: ", self.inputFiducialSelector) # # input model selector # self.inputModelSelector = slicer.qMRMLNodeComboBox() self.inputModelSelector.nodeTypes = ( ("vtkMRMLModelNode"), "" ) 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( "Pick the input model for the algorithm." ) parametersFormLayout.addRow("Input model: ", self.inputModelSelector) # # output transform selector # self.outputSelector = slicer.qMRMLNodeComboBox() self.outputSelector.nodeTypes = ( ("vtkMRMLLinearTransformNode"), "" ) self.outputSelector.selectNodeUponCreation = True self.outputSelector.addEnabled = True self.outputSelector.removeEnabled = True self.outputSelector.noneEnabled = False self.outputSelector.showHidden = False self.outputSelector.showChildNodeTypes = False self.outputSelector.renameEnabled = True self.outputSelector.setMRMLScene( slicer.mrmlScene ) self.outputSelector.setToolTip( "Pick the output to the algorithm." ) parametersFormLayout.addRow("Output transform: ", self.outputSelector) # # check box to trigger taking screen shots for later use in tutorials # self.enableScreenshotsFlagCheckBox = qt.QCheckBox() self.enableScreenshotsFlagCheckBox.checked = 0 self.enableScreenshotsFlagCheckBox.setToolTip("If checked, take screen shots for tutorials. Use Save Data to write them to disk.") # parametersFormLayout.addRow("Enable Screenshots", self.enableScreenshotsFlagCheckBox) # # scale factor for screen shots # self.screenshotScaleFactorSliderWidget = ctk.ctkSliderWidget() self.screenshotScaleFactorSliderWidget.singleStep = 1.0 self.screenshotScaleFactorSliderWidget.minimum = 1.0 self.screenshotScaleFactorSliderWidget.maximum = 50.0 self.screenshotScaleFactorSliderWidget.value = 1.0 self.screenshotScaleFactorSliderWidget.setToolTip("Set scale factor for the screen shots.") # # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Run the algorithm." self.applyButton.enabled = False parametersFormLayout.addRow(self.applyButton) # # Output panel # outputCollapsibleButton = ctk.ctkCollapsibleButton() outputCollapsibleButton.text = "Output" self.layout.addWidget( outputCollapsibleButton ) outputFormLayout = qt.QFormLayout( outputCollapsibleButton ) self.outputLine = qt.QLineEdit() self.outputLine.setReadOnly( True ) outputFormLayout.addRow( "Mean distance after registration:", self.outputLine ) # # Advanced parameters # advancedCollapsibleButton = ctk.ctkCollapsibleButton() advancedCollapsibleButton.text = "Advanced" self.layout.addWidget(advancedCollapsibleButton) # Layout advancedCollapsibleButton.collapsed = True advancedFormLayout = qt.QFormLayout(advancedCollapsibleButton) # # Transform type selector # self.typeSelector = qt.QComboBox() self.typeSelector.insertItem( 0, "Rigid" ) self.typeSelector.insertItem( 1, "Similarity" ) self.typeSelector.insertItem( 2, "Affine" ) advancedFormLayout.addRow("Transform type: ", self.typeSelector) # # Iteration selector # self.iterationSpin = qt.QSpinBox() self.iterationSpin.setMaximum( 1000 ) self.iterationSpin.setValue( 100 ) advancedFormLayout.addRow("Number of iterations:", self.iterationSpin) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) self.inputModelSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) self.inputFiducialSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) self.outputSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) # Add vertical spacer self.layout.addStretch(1)
def setup(self): # # Reload and Test area # reloadCollapsibleButton = ctk.ctkCollapsibleButton() reloadCollapsibleButton.text = "Reload && Test" self.layout.addWidget(reloadCollapsibleButton) reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton) # reload button # (use this during development, but remove it when delivering # your module to users) self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "Radiomics Reload" reloadFormLayout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # reload and test button # (use this during development, but remove it when delivering # your module to users) self.reloadAndTestButton = qt.QPushButton("Reload and Test") self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests." reloadFormLayout.addWidget(self.reloadAndTestButton) # self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest) reloadCollapsibleButton.collapsed = True #--------------------------------------------------------- # # Compute Radiomics area # self.computeRadiomicsCollapsibleButton = ctk.ctkCollapsibleButton() self.computeRadiomicsCollapsibleButton.text = "Slicer Radiomics Platform" self.layout.addWidget(self.computeRadiomicsCollapsibleButton) self.computeRadiomicsFormLayout = qt.QFormLayout( self.computeRadiomicsCollapsibleButton) # # Universal Advanced Settings Collapsible Button # self.AdvancedSettingsCollapsibleButton = ctk.ctkCollapsibleButton() self.AdvancedSettingsCollapsibleButton.text = "Advanced Settings" self.AdvancedSettingsCollapsibleButtonLayout = qt.QHBoxLayout() self.AdvancedSettingsCollapsibleButton.setLayout(qt.QHBoxLayout()) self.computeRadiomicsFormLayout.addWidget( self.AdvancedSettingsCollapsibleButton) self.AdvancedSettingsCollapsibleButton.collapsed = True self.AdvancedSettingsFrame = qt.QFrame( self.AdvancedSettingsCollapsibleButton) self.AdvancedSettingsFrameLayout = qt.QFormLayout() self.AdvancedSettingsFrame.setLayout(self.AdvancedSettingsFrameLayout) self.AdvancedSettingsCollapsibleButton.layout().addWidget( self.AdvancedSettingsFrame) # Label Values self.inputLabelValues = qt.QLabel("Label Values:", self.AdvancedSettingsFrame) self.inputLabelValuesField = qt.QLineEdit("1", self.AdvancedSettingsFrame) self.AdvancedSettingsFrameLayout.addRow(self.inputLabelValues, self.inputLabelValuesField) # Interpolation Settings self.settingsRadioButtonFrame = qt.QFrame(self.AdvancedSettingsFrame) self.settingsRadioButtonFrame.setLayout(qt.QHBoxLayout()) self.interpolationsGroup = qt.QButtonGroup( self.settingsRadioButtonFrame) self.ipRawButton = qt.QRadioButton("Raw") self.ip1x1x1Button = qt.QRadioButton("(1,1,1)") self.ip2x2x2Button = qt.QRadioButton("(2,2,2)") self.ip3x3x3Button = qt.QRadioButton("(3,3,3)") self.ipRawButton.checked = True self.interpolationsGroup.addButton(self.ipRawButton) self.interpolationsGroup.addButton(self.ip1x1x1Button) self.interpolationsGroup.addButton(self.ip2x2x2Button) self.interpolationsGroup.addButton(self.ip3x3x3Button) self.settingsRadioButtonFrame.layout().addWidget(self.ipRawButton) self.settingsRadioButtonFrame.layout().addWidget(self.ip1x1x1Button) self.settingsRadioButtonFrame.layout().addWidget(self.ip2x2x2Button) self.settingsRadioButtonFrame.layout().addWidget(self.ip3x3x3Button) self.interpHeader = qt.QLabel("Interpolation:") self.AdvancedSettingsFrameLayout.addRow(self.interpHeader, self.settingsRadioButtonFrame) # Bin Width self.inputBinWidth = qt.QLabel("Bin Width:", self.AdvancedSettingsFrame) self.inputBinWidthField = qt.QLineEdit("25", self.AdvancedSettingsFrame) self.AdvancedSettingsFrameLayout.addRow(self.inputBinWidth, self.inputBinWidthField) # Modality Radio Buttons Frame self.ModalityRadioButtonFrame = qt.QFrame(self.AdvancedSettingsFrame) self.ModalityRadioButtonFrame.setLayout(qt.QHBoxLayout()) self.ModalityFileFormatGroup = qt.QButtonGroup( self.ModalityRadioButtonFrame) self.CTButton = qt.QRadioButton("CT") self.CTButton.checked = True self.MRIButton = qt.QRadioButton("MRI") self.PETButton = qt.QRadioButton("PET") self.ModalityFileFormatGroup.addButton(self.CTButton) self.ModalityFileFormatGroup.addButton(self.MRIButton) self.ModalityFileFormatGroup.addButton(self.PETButton) self.ModalityRadioButtonFrame.layout().addWidget(self.CTButton) self.ModalityRadioButtonFrame.layout().addWidget(self.MRIButton) self.ModalityRadioButtonFrame.layout().addWidget(self.PETButton) self.ModalityInputLabel = qt.QLabel("Image Modality:", self.AdvancedSettingsFrame) self.AdvancedSettingsFrameLayout.addRow(self.ModalityInputLabel, self.ModalityRadioButtonFrame) # # End Universal Advanced Settings Collapsible Button # # Parent Tab Widget self.computeRadiomicsTabWidget = qt.QTabWidget() self.computeRadiomicsFormLayout.addWidget( self.computeRadiomicsTabWidget) # Radiomics Current Mode self.tabComputeRadiomicsCurr = qt.QWidget() self.singleCaseInputFormLayout = qt.QFormLayout() self.tabComputeRadiomicsCurr.setLayout(self.singleCaseInputFormLayout) self.tabComputeRadiomicsCurrName = "Single Case Mode" self.computeRadiomicsTabWidget.addTab(self.tabComputeRadiomicsCurr, self.tabComputeRadiomicsCurrName) # Input 1: Input Image self.input1Frame = qt.QFrame(self.tabComputeRadiomicsCurr) self.input1Frame.setLayout(qt.QHBoxLayout()) self.singleCaseInputFormLayout.addWidget(self.input1Frame) self.input1Selector = qt.QLabel("Input Image: ", self.input1Frame) self.input1Frame.layout().addWidget(self.input1Selector) self.input1Selector = slicer.qMRMLNodeComboBox(self.input1Frame) self.input1Selector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.input1Selector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", 0) self.input1Selector.addEnabled = False self.input1Selector.removeEnabled = False self.input1Selector.setMRMLScene(slicer.mrmlScene) self.input1Frame.layout().addWidget(self.input1Selector) # Input 2: Input Segmentation self.input2Frame = qt.QFrame(self.tabComputeRadiomicsCurr) self.input2Frame.setLayout(qt.QHBoxLayout()) self.singleCaseInputFormLayout.addWidget(self.input2Frame) self.input2Selector = qt.QLabel("Input Label: ", self.input2Frame) self.input2Frame.layout().addWidget(self.input2Selector) self.input2Selector = slicer.qMRMLNodeComboBox(self.input2Frame) self.input2Selector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.input2Selector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", 1) self.input2Selector.addEnabled = False self.input2Selector.removeEnabled = False self.input2Selector.setMRMLScene(slicer.mrmlScene) self.input2Frame.layout().addWidget(self.input2Selector) # Settings Collapsible Button self.SettingsCollapsibleButtonCurr = ctk.ctkCollapsibleButton() self.SettingsCollapsibleButtonCurr.text = "Settings" self.SettingsCollapsibleButtonCurrLayout = qt.QHBoxLayout() self.SettingsCollapsibleButtonCurr.setLayout( self.SettingsCollapsibleButtonCurrLayout) self.singleCaseInputFormLayout.addWidget( self.SettingsCollapsibleButtonCurr) self.SettingsCollapsibleButtonCurr.collapsed = False self.SettingsFrameCurr = qt.QFrame(self.SettingsCollapsibleButtonCurr) self.SettingsFrameCurr.setLayout(qt.QFormLayout()) self.SettingsCollapsibleButtonCurrLayout.addWidget( self.SettingsFrameCurr) # Settings self.para2curr = qt.QCheckBox("Use MatlabBridge", self.tabComputeRadiomicsCurr) self.para2curr.toolTip = "When checked: Matlab features extracted" self.para2curr.checked = False self.SettingsFrameCurr.layout().addRow(self.para2curr) # Apply Radiomics button self.RadiomicCurrButtonsFrame = qt.QFrame(self.tabComputeRadiomicsCurr) self.RadiomicCurrButtonsFrame.setLayout(qt.QHBoxLayout()) self.singleCaseInputFormLayout.addWidget(self.RadiomicCurrButtonsFrame) self.radiomicsCurrButton = qt.QPushButton( "Compute Radiomics Features (Single Case)", self.RadiomicCurrButtonsFrame) self.radiomicsCurrButton.enabled = True self.radiomicsCurrButton.toolTip = "Run the feature extraction for a single case." self.RadiomicCurrButtonsFrame.layout().addWidget( self.radiomicsCurrButton) # Chart self.RadiomicsTableFrame = qt.QFrame(self.tabComputeRadiomicsCurr) self.RadiomicsTableFrameLayout = qt.QHBoxLayout() self.RadiomicsTableFrame.setLayout(self.RadiomicsTableFrameLayout) self.singleCaseInputFormLayout.addWidget(self.RadiomicsTableFrame) self.RadiomicsTableView = qt.QTableView(self.RadiomicsTableFrame) self.RadiomicsTableView.sortingEnabled = True self.RadiomicsTableView.minimumHeight = 175 self.RadiomicsTableView.verticalHeader().visible = False self.RadiomicsTableView.setColumnWidth(0, 30) self.RadiomicsTableFrameLayout.addWidget(self.RadiomicsTableView) self.RadiomicsTableModel = qt.QStandardItemModel() # Save Table Button self.saveButton = qt.QPushButton("Save Table to CSV File", self.RadiomicCurrButtonsFrame) self.saveButton.toolTip = "Save Radiomics Feature from table to CSV file" self.saveButton.enabled = False self.singleCaseInputFormLayout.layout().addWidget(self.saveButton) """ # # The interface we use for batch mode (not part of this module) # #--------------------------------------------------------- # Radiomics Batch self.tabComputeRadiomicsBatch = qt.QWidget() self.RadiomicsFormLayout = qt.QFormLayout() self.tabComputeRadiomicsBatch.setLayout(self.RadiomicsFormLayout) self.tabComputeRadiomicsBatchName = "Batch Mode" self.computeRadiomicsTabWidget.addTab(self.tabComputeRadiomicsBatch, self.tabComputeRadiomicsBatchName) # Input 3: Database selection self.input3Frame = qt.QFrame(self.tabComputeRadiomicsBatch) self.input3Frame.setLayout(qt.QHBoxLayout()) self.RadiomicsFormLayout.addWidget(self.input3Frame) self.DatabaseButton = qt.QPushButton("Set Root Patient Directory") self.DatabaseButton.toolTip = "Set the main Patient Data location" self.DatabaseButton.enabled = True self.input3Frame.layout().addWidget(self.DatabaseButton) self.PatientSelector = qt.QComboBox() self.PatientSelector.enabled = False self.input3Frame.layout().addWidget(self.PatientSelector) # Settings Collapsible Button self.SettingsCollapsibleButton = ctk.ctkCollapsibleButton() self.SettingsCollapsibleButton.text = "Settings" self.SettingsCollapsibleButtonLayout = qt.QHBoxLayout() self.SettingsCollapsibleButton.setLayout(self.SettingsCollapsibleButtonLayout) self.RadiomicsFormLayout.addWidget(self.SettingsCollapsibleButton) self.SettingsCollapsibleButton.collapsed = False self.SettingsFrame = qt.QFrame(self.SettingsCollapsibleButton) self.SettingsFrame.setLayout(qt.QFormLayout()) self.SettingsCollapsibleButtonLayout.addWidget(self.SettingsFrame) # Settings self.para2 = qt.QCheckBox("Use MatlabBridge", self.SettingsFrame) self.para2.toolTip = "When checked: Matlab features extracted" self.para2.checked = True self.SettingsFrame.layout().addRow(self.para2) self.para3 = qt.QCheckBox("Clear Database", self.SettingsFrame) self.para3.toolTip = "When checked: old database is cleared" self.para3.checked = True self.SettingsFrame.layout().addRow(self.para3) # Keywords Collapsible Button self.KeywordsCollapsibleButton = ctk.ctkCollapsibleButton() self.KeywordsCollapsibleButton.text = "Keyword Matching" self.KeywordsCollapsibleButtonLayout = qt.QHBoxLayout() self.KeywordsCollapsibleButton.setLayout(self.KeywordsCollapsibleButtonLayout) self.SettingsFrame.layout().addRow(self.KeywordsCollapsibleButton) self.KeywordsCollapsibleButton.collapsed = True self.keywordsFrame = qt.QFrame(self.KeywordsCollapsibleButton) self.keywordsFrame.setLayout(qt.QFormLayout()) self.KeywordsCollapsibleButtonLayout.addWidget(self.keywordsFrame) self.keywordsHeader = qt.QLabel("Keyword Matching:", self.keywordsFrame) self.keywordsFrame.layout().addRow(self.keywordsHeader) # File Type Radio Buttons Frame self.radioButtonFrame = qt.QFrame(self.keywordsFrame) self.radioButtonFrame.setLayout(qt.QFormLayout()) self.fileFormatGroup = qt.QButtonGroup(self.radioButtonFrame) self.nrrdButton = qt.QRadioButton("NRRD") self.nrrdButton.checked = True self.niftiButton = qt.QRadioButton("NIFTI") self.fileFormatGroup.addButton(self.nrrdButton) self.fileFormatGroup.addButton(self.niftiButton) self.radioButtonFrame.layout().addRow(self.nrrdButton, self.niftiButton) self.inputMaskHeader = qt.QLabel("Input Image File Type:", self.keywordsFrame) self.keywordsFrame.layout().addRow(self.inputMaskHeader, self.radioButtonFrame) # Keywords Frame self.inputImageKeywords = qt.QLabel("Input Image Keywords:", self.keywordsFrame) self.inputImageKeywordsField = qt.QLineEdit("",self.keywordsFrame) self.keywordsFrame.layout().addRow(self.inputImageKeywords, self.inputImageKeywordsField ) self.inputImageExclusionKeywords = qt.QLabel("Input Image Exclusion Keywords:", self.keywordsFrame) self.inputImageExclusionKeywordsField = qt.QLineEdit("",self.keywordsFrame) self.keywordsFrame.layout().addRow(self.inputImageExclusionKeywords, self.inputImageExclusionKeywordsField ) self.inputLabelKeywords = qt.QLabel("Input Label Keywords:", self.keywordsFrame) self.inputLabelKeywordsField = qt.QLineEdit("",self.keywordsFrame) self.keywordsFrame.layout().addRow(self.inputLabelKeywords, self.inputLabelKeywordsField ) self.inputLabelExclusionKeywords = qt.QLabel("Input Label Exclusion Keywords:", self.keywordsFrame) self.inputLabelExclusionKeywordsField = qt.QLineEdit("",self.keywordsFrame) self.keywordsFrame.layout().addRow(self.inputLabelExclusionKeywords, self.inputLabelExclusionKeywordsField ) # Radiomic Mode Buttons self.RadiomicButtonsFrame = qt.QFrame(self.tabComputeRadiomicsBatch) self.RadiomicButtonsFrame.setLayout(qt.QHBoxLayout()) self.RadiomicsFormLayout.addWidget(self.RadiomicButtonsFrame) self.radiomicsBatchButton = qt.QPushButton("Compute Radiomics Features (Batch Mode)") self.radiomicsBatchButton.toolTip = "Run the feature extraction for database batch." self.radiomicsBatchButton.enabled = True self.RadiomicButtonsFrame.layout().addWidget(self.radiomicsBatchButton) self.RadiomicButtonsFrame.enabled = True """ #--------------------------------------------------------- # Connections #self.DatabaseButton.connect('clicked(bool)', self.onDatabaseButton) self.radiomicsCurrButton.connect('clicked(bool)', self.onRadiomicsCurr) #self.radiomicsBatchButton.connect('clicked(bool)', self.onRadiomicsBatch) self.saveButton.connect('clicked()', self.onSave) self.layout.addStretch(1) # Add vertical spacer
def setup(self): # Instantiate and connect widgets ... if self.developerMode: # # Reload and Test area # reloadCollapsibleButton = ctk.ctkCollapsibleButton() reloadCollapsibleButton.text = "Reload && Test" self.layout.addWidget(reloadCollapsibleButton) reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton) # reload button # (use this during development, but remove it when delivering # your module to users) self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "CompareVolumes Reload" reloadFormLayout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # reload and test button # (use this during development, but remove it when delivering # your module to users) self.reloadAndTestButton = qt.QPushButton("Reload and Test All") self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests." reloadFormLayout.addWidget(self.reloadAndTestButton) self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest) # reload and run specific tests scenarios = ( "Three Volume", "View Watcher", "LayerReveal", ) for scenario in scenarios: button = qt.QPushButton("Reload and Test %s" % scenario) self.reloadAndTestButton.toolTip = "Reload this module and then run the %s self test." % scenario reloadFormLayout.addWidget(button) button.connect( 'clicked()', lambda s=scenario: self.onReloadAndTest(scenario=s)) # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) # # orientation # self.orientationBox = qt.QGroupBox("Orientation") self.orientationBox.setLayout(qt.QFormLayout()) self.orientationButtons = {} self.orientations = ("Axial", "Sagittal", "Coronal") for orientation in self.orientations: self.orientationButtons[orientation] = qt.QRadioButton() self.orientationButtons[orientation].text = orientation self.orientationButtons[orientation].connect( "clicked()", lambda o=orientation: self.setOrientation(o)) self.orientationBox.layout().addWidget( self.orientationButtons[orientation]) parametersFormLayout.addWidget(self.orientationBox) self.setOrientation(self.orientations[0]) # # target volume selector # self.inputSelector = slicer.qMRMLNodeComboBox() self.inputSelector.nodeTypes = (("vtkMRMLVolumeNode"), "") self.inputSelector.selectNodeUponCreation = True self.inputSelector.addEnabled = False self.inputSelector.removeEnabled = False self.inputSelector.noneEnabled = False self.inputSelector.showHidden = False self.inputSelector.showChildNodeTypes = True self.inputSelector.setMRMLScene(slicer.mrmlScene) self.inputSelector.setToolTip("Pick the input to the algorithm.") parametersFormLayout.addRow("Target Volume: ", self.inputSelector) # # lightbox # self.lightboxVolumeButton = qt.QPushButton("Lightbox Target Volume") self.lightboxVolumeButton.setToolTip( "Make a set of slice views that span the extent of this study at equally spaced locations in the selected orientation." ) parametersFormLayout.addRow(self.lightboxVolumeButton) self.lightboxVolumeButton.connect("clicked()", self.onLightboxVolume) # # background volume selector # self.backgroundSelector = slicer.qMRMLNodeComboBox() self.backgroundSelector.nodeTypes = (("vtkMRMLVolumeNode"), "") self.backgroundSelector.selectNodeUponCreation = True self.backgroundSelector.addEnabled = False self.backgroundSelector.removeEnabled = False self.backgroundSelector.noneEnabled = True self.backgroundSelector.showHidden = False self.backgroundSelector.showChildNodeTypes = True self.backgroundSelector.setMRMLScene(slicer.mrmlScene) self.backgroundSelector.setToolTip( "Common background - all lightbox panes will have this background and a different volume in each foreground." ) parametersFormLayout.addRow("Common Background Volume: ", self.backgroundSelector) # # label volume selector # self.labelSelector = slicer.qMRMLNodeComboBox() self.labelSelector.nodeTypes = (("vtkMRMLLabelMapVolumeNode"), "") self.labelSelector.selectNodeUponCreation = True self.labelSelector.addEnabled = False self.labelSelector.removeEnabled = False self.labelSelector.noneEnabled = True self.labelSelector.showHidden = False self.labelSelector.showChildNodeTypes = True self.labelSelector.setMRMLScene(slicer.mrmlScene) self.labelSelector.setToolTip( "Common label - all lightbox panes will have this label on top.") parametersFormLayout.addRow("Common Label Volume: ", self.labelSelector) self.lightboxVolumesButton = qt.QPushButton("Lightbox All Volumes") self.lightboxVolumesButton.setToolTip( "Make a set of slice views that show each of the currently loaded volumes, with optional companion volumes, in the selected orientation." ) parametersFormLayout.addRow(self.lightboxVolumesButton) self.lightboxVolumesButton.connect("clicked()", self.onLightboxVolumes) # # Add layer reveal area # layerRevealCollapsibleButton = ctk.ctkCollapsibleButton() layerRevealCollapsibleButton.text = "Layer Reveal Cursor" self.layout.addWidget(layerRevealCollapsibleButton) layerRevealFormLayout = qt.QFormLayout(layerRevealCollapsibleButton) self.layerRevealCheck = qt.QCheckBox() layerRevealFormLayout.addRow("Layer Reveal Cursor", self.layerRevealCheck) self.layerRevealCheck.connect("toggled(bool)", self.onLayerRevealToggled) # Add vertical spacer self.layout.addStretch(1)
def setup(self): # Instantiate and connect widgets ... # reload button # (use this during development, but remove it when delivering # your module to users) self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "RSNAQuantTutorial Reload" self.layout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # reload and test button # (use this during development, but remove it when delivering # your module to users) self.reloadAndTestButton = qt.QPushButton("Reload and Test") self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests." self.layout.addWidget(self.reloadAndTestButton) self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest) # Collapsible button testsCollapsibleButton = ctk.ctkCollapsibleButton() testsCollapsibleButton.text = "Tests" self.layout.addWidget(testsCollapsibleButton) # Layout within the collapsible button formLayout = qt.QFormLayout(testsCollapsibleButton) # test buttons tests = (("Part 1 : Ruler", self.onPart1Ruler), ("Part 2: ChangeTracker", self.onPart2ChangeTracker), ("Part 3 : PETCT", self.onPart3PETCT)) for text, slot in tests: testButton = qt.QPushButton(text) testButton.toolTip = "Run the test." formLayout.addWidget(testButton) testButton.connect('clicked(bool)', slot) # A collapsible button to hide screen shot options screenShotsCollapsibleButton = ctk.ctkCollapsibleButton() screenShotsCollapsibleButton.text = "Screen shot options" self.layout.addWidget(screenShotsCollapsibleButton) # layout within the collapsible button screenShotsFormLayout = qt.QFormLayout(screenShotsCollapsibleButton) # # check box to trigger taking screen shots for later use in tutorials # self.enableScreenshotsFlagCheckBox = qt.QCheckBox() self.enableScreenshotsFlagCheckBox.checked = 0 self.enableScreenshotsFlagCheckBox.setToolTip( "If checked, take screen shots for tutorials. Use Save Data to write them to disk." ) screenShotsFormLayout.addRow("Enable Screenshots", self.enableScreenshotsFlagCheckBox) # # scale factor for screen shots # self.screenshotScaleFactorSliderWidget = ctk.ctkSliderWidget() self.screenshotScaleFactorSliderWidget.singleStep = 1.0 self.screenshotScaleFactorSliderWidget.minimum = 1.0 self.screenshotScaleFactorSliderWidget.maximum = 50.0 self.screenshotScaleFactorSliderWidget.value = 1.0 self.screenshotScaleFactorSliderWidget.setToolTip( "Set scale factor for the screen shots.") screenShotsFormLayout.addRow("Screenshot scale factor", self.screenshotScaleFactorSliderWidget) # Add vertical spacer self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) # ground truth transform selector self.groundTruthTransformSelectorLabel = qt.QLabel() self.groundTruthTransformSelectorLabel.setText( "Ground truth transform: " ) self.groundTruthTransformSelector = slicer.qMRMLNodeComboBox() self.groundTruthTransformSelector.nodeTypes = ( ["vtkMRMLTransformNode"] ) self.groundTruthTransformSelector.noneEnabled = False self.groundTruthTransformSelector.addEnabled = True self.groundTruthTransformSelector.removeEnabled = True self.groundTruthTransformSelector.setMRMLScene( slicer.mrmlScene ) self.groundTruthTransformSelector.setToolTip( "Pick the input ground truth transform (e.g., optical tracker)" ) parametersFormLayout.addRow(self.groundTruthTransformSelectorLabel, self.groundTruthTransformSelector) # mapped transform selector self.mappedTransformSelectorLabel = qt.QLabel("Mapped transform: ") self.mappedTransformSelector = slicer.qMRMLNodeComboBox() self.mappedTransformSelector.nodeTypes = ( ["vtkMRMLTransformNode"] ) self.mappedTransformSelector.noneEnabled = False self.mappedTransformSelector.addEnabled = True self.mappedTransformSelector.removeEnabled = True self.mappedTransformSelector.setMRMLScene( slicer.mrmlScene ) self.mappedTransformSelector.setToolTip( "Pick the input transform to be mapped compared to the ground truth (e.g., electromagnetic tracker)" ) parametersFormLayout.addRow(self.mappedTransformSelectorLabel, self.mappedTransformSelector) # output volume selector self.outputVisitedPointsModelSelectorLabel = qt.QLabel("Output visited points model: ") self.outputVisitedPointsModelSelector = slicer.qMRMLNodeComboBox() self.outputVisitedPointsModelSelector.nodeTypes = ( ["vtkMRMLModelNode"] ) self.outputVisitedPointsModelSelector.noneEnabled = True self.outputVisitedPointsModelSelector.addEnabled = True self.outputVisitedPointsModelSelector.removeEnabled = True self.outputVisitedPointsModelSelector.baseName = "VisitedPoints" self.outputVisitedPointsModelSelector.setMRMLScene( slicer.mrmlScene ) self.outputVisitedPointsModelSelector.setToolTip( "A glyph is added to the model at each measurement point. Optional." ) parametersFormLayout.addRow(self.outputVisitedPointsModelSelectorLabel, self.outputVisitedPointsModelSelector) # Position error vector self.positionErrorTransformSelectorLabel = qt.QLabel("Position error transform: ") self.positionErrorTransformSelector = slicer.qMRMLNodeComboBox() self.positionErrorTransformSelector.nodeTypes = ( ["vtkMRMLTransformNode"] ) self.positionErrorTransformSelector.noneEnabled = True self.positionErrorTransformSelector.addEnabled = True self.positionErrorTransformSelector.removeEnabled = True self.positionErrorTransformSelector.baseName = "PositionErrorTransform" self.positionErrorTransformSelector.setMRMLScene( slicer.mrmlScene ) self.positionErrorTransformSelector.setToolTip( "The transform node will store and interpolate the measurement points to generate a vector field of the position error of the mapped transform compared to the ground truth transform. Optional." ) parametersFormLayout.addRow(self.positionErrorTransformSelectorLabel, self.positionErrorTransformSelector) # Orientation error magnitude self.orientationErrorTransformSelectorLabel = qt.QLabel("Orientation error transform:") self.orientationErrorTransformSelector = slicer.qMRMLNodeComboBox() self.orientationErrorTransformSelector.nodeTypes = ( ["vtkMRMLTransformNode"] ) self.orientationErrorTransformSelector.noneEnabled = True self.orientationErrorTransformSelector.addEnabled = True self.orientationErrorTransformSelector.removeEnabled = True self.orientationErrorTransformSelector.baseName = "OrientationErrorTransform" self.orientationErrorTransformSelector.setMRMLScene( slicer.mrmlScene ) self.orientationErrorTransformSelector.setToolTip( "The transform node will store and interpolate the measurement points to generate a vector field of the orientation error of the mapped transform compared to the ground truth transform. Only the x component is used. Optional." ) parametersFormLayout.addRow(self.orientationErrorTransformSelectorLabel, self.orientationErrorTransformSelector) # Select defaults (to make debugging easier) emPointerToEmTrackerNode = slicer.util.getNode('EmPointerToEmTracker') if emPointerToEmTrackerNode: self.mappedTransformSelector.setCurrentNode(emPointerToEmTrackerNode) emPointerGtruthToOpPointerNode = slicer.util.getNode('EmPointerGtruthToOpPointer') if emPointerGtruthToOpPointerNode: self.groundTruthTransformSelector.setCurrentNode(emPointerGtruthToOpPointerNode) visitedPointsModelNode = slicer.util.getNode('VisitedPoints') if visitedPointsModelNode: self.outputVisitedPointsModelSelector.setCurrentNode(visitedPointsModelNode) positionErrorTransformNode = slicer.util.getNode('PositionErrorTransform') if positionErrorTransformNode: self.positionErrorTransformSelector.setCurrentNode(positionErrorTransformNode) orientationErrorTransformNode = slicer.util.getNode('OrientationErrorTransform') if orientationErrorTransformNode: self.orientationErrorTransformSelector.setCurrentNode(orientationErrorTransformNode) # # Check box to enable creating output transforms automatically. # The function is useful for testing and initial creation of the transforms but not recommended when the # transforms are already in the scene. # self.enableTransformMappingCheckBox = qt.QCheckBox() self.enableTransformMappingCheckBox.checked = 0 self.enableTransformMappingCheckBox.setToolTip("If checked, then the mapped transform difference compared to the ground truth is written into the volume.") parametersFormLayout.addRow("Enable mapping", self.enableTransformMappingCheckBox) self.enableTransformMappingCheckBox.connect('stateChanged(int)', self.setEnableTransformMapping) # # View current error area # errorCollapsibleButton = ctk.ctkCollapsibleButton() errorCollapsibleButton.text = "Current Error" self.layout.addWidget(errorCollapsibleButton) errorFormLayout = qt.QFormLayout(errorCollapsibleButton) self.errorPositionLabel = qt.QLabel("Position error (mm): ") self.errorPositionValueLabel = qt.QLabel() self.errorOrientationLabel = qt.QLabel("Orientation error (deg): ") self.errorOrientationValueLabel = qt.QLabel() self.errorXLabel = qt.QLabel("Error in X-value (mm): ") self.errorXValueLabel = qt.QLabel() self.errorYLabel = qt.QLabel("Error in Y-value (mm): ") self.errorYValueLabel = qt.QLabel() self.errorZLabel = qt.QLabel("Error in Z-value (mm): ") self.errorZValueLabel = qt.QLabel() errorFormLayout.addRow(self.errorPositionLabel, self.errorPositionValueLabel) errorFormLayout.addRow(self.errorOrientationLabel, self.errorOrientationValueLabel) errorFormLayout.addRow(self.errorXLabel, self.errorXValueLabel) errorFormLayout.addRow(self.errorYLabel, self.errorYValueLabel) errorFormLayout.addRow(self.errorZLabel, self.errorZValueLabel) # # Export Area # exportCollapsibleButton = ctk.ctkCollapsibleButton() exportCollapsibleButton.text = "Export" self.layout.addWidget(exportCollapsibleButton) exportFormLayout = qt.QFormLayout(exportCollapsibleButton) # ROI selector self.exportRoiSelectorLabel = qt.QLabel() self.exportRoiSelectorLabel.setText( "Region of interest: " ) self.exportRoiSelector = slicer.qMRMLNodeComboBox() self.exportRoiSelector.nodeTypes = ( "vtkMRMLAnnotationROINode", "" ) self.exportRoiSelector.noneEnabled = False self.exportRoiSelector.addEnabled = False self.exportRoiSelector.removeEnabled = True self.exportRoiSelector.setMRMLScene( slicer.mrmlScene ) self.exportRoiSelector.setToolTip( "Pick the input region of interest for export" ) exportFormLayout.addRow(self.exportRoiSelectorLabel, self.exportRoiSelector) # Export button self.exportButton = qt.QPushButton("Export") self.exportButton.toolTip = "Export the transform in the selected region of interest to a vector volume" self.exportButton.enabled = True exportFormLayout.addRow(self.exportButton) self.exportButton.connect('clicked(bool)', self.onExport) # Add vertical spacer self.layout.addStretch(1)
def setup(self): ScriptedLoadableModuleWidget.setup(self) # Instantiate and connect widgets ... # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) self.inputDirSelector = ctk.ctkPathLineEdit() self.inputDirSelector.filters = ctk.ctkPathLineEdit.Dirs self.inputDirSelector.settingKey = 'DICOMPatcherInputDir' parametersFormLayout.addRow("Input DICOM directory:", self.inputDirSelector) self.outputDirSelector = ctk.ctkPathLineEdit() self.outputDirSelector.filters = ctk.ctkPathLineEdit.Dirs self.outputDirSelector.settingKey = 'DICOMPatcherOutputDir' parametersFormLayout.addRow("Output DICOM directory:", self.outputDirSelector) self.normalizeFileNamesCheckBox = qt.QCheckBox() self.normalizeFileNamesCheckBox.checked = True self.normalizeFileNamesCheckBox.setToolTip( "Replace file and folder names with automatically generated names." " Fixes errors caused by file path containins special characters or being too long." ) parametersFormLayout.addRow("Normalize file names", self.normalizeFileNamesCheckBox) self.forceSamePatientNameIdInEachDirectoryCheckBox = qt.QCheckBox() self.forceSamePatientNameIdInEachDirectoryCheckBox.checked = False self.forceSamePatientNameIdInEachDirectoryCheckBox.setToolTip( "Generate patient name and ID from the first file in a directory" " and force all other files in the same directory to have the same patient name and ID." " Enable this option if a separate patient directory is created for each patched file." ) parametersFormLayout.addRow( "Force same patient name and ID in each directory", self.forceSamePatientNameIdInEachDirectoryCheckBox) self.generateMissingIdsCheckBox = qt.QCheckBox() self.generateMissingIdsCheckBox.checked = True self.generateMissingIdsCheckBox.setToolTip( "Generate missing patient, study, series IDs. It is assumed that" " all files in a directory belong to the same series. Fixes error caused by too aggressive anonymization" " or incorrect DICOM image converters.") parametersFormLayout.addRow( "Generate missing patient/study/series IDs", self.generateMissingIdsCheckBox) self.generateImagePositionFromSliceThicknessCheckBox = qt.QCheckBox() self.generateImagePositionFromSliceThicknessCheckBox.checked = True self.generateImagePositionFromSliceThicknessCheckBox.setToolTip( "Generate 'image position sequence' for" " multi-frame files that only have 'SliceThickness' field. Fixes error in Dolphin 3D CBCT scanners." ) parametersFormLayout.addRow( "Generate slice position for multi-frame volumes", self.generateImagePositionFromSliceThicknessCheckBox) self.anonymizeDicomCheckBox = qt.QCheckBox() self.anonymizeDicomCheckBox.checked = False self.anonymizeDicomCheckBox.setToolTip( "If checked, then some patient identifiable information will be removed" " from the patched DICOM files. There are many fields that can identify a patient, this function does not remove all of them." ) parametersFormLayout.addRow("Partially anonymize", self.anonymizeDicomCheckBox) # # Patch Button # self.patchButton = qt.QPushButton("Patch") self.patchButton.toolTip = "Fix DICOM files in input directory and write them to output directory" parametersFormLayout.addRow(self.patchButton) # # Import Button # self.importButton = qt.QPushButton("Import") self.importButton.toolTip = "Import DICOM files in output directory into Slicer DICOM database" parametersFormLayout.addRow(self.importButton) # # Switch to DICOM module Button # self.switchToDICOMModuleButton = qt.QPushButton("Go to DICOM module") self.switchToDICOMModuleButton.toolTip = "Open DICOM module where imported data can be loaded into the scene" parametersFormLayout.addRow(self.switchToDICOMModuleButton) # connections self.patchButton.connect('clicked(bool)', self.onPatchButton) self.importButton.connect('clicked(bool)', self.onImportButton) self.switchToDICOMModuleButton.connect( 'clicked(bool)', self.onSwitchToDICOMModuleButton) self.statusLabel = qt.QPlainTextEdit() self.statusLabel.setTextInteractionFlags(qt.Qt.TextSelectableByMouse) parametersFormLayout.addRow(self.statusLabel) # Add vertical spacer self.layout.addStretch(1) self.logic = DICOMPatcherLogic() self.logic.logCallback = self.addLog
def create(self): """create the segmentation helper box""" # # Master Frame # self.masterFrame = qt.QFrame(self.parent) self.masterFrame.setLayout(qt.QVBoxLayout()) self.parent.layout().addWidget(self.masterFrame) # # the master volume selector # self.masterSelectorFrame = qt.QFrame(self.parent) self.masterSelectorFrame.objectName = 'MasterVolumeFrame' self.masterSelectorFrame.setLayout(qt.QHBoxLayout()) self.masterFrame.layout().addWidget(self.masterSelectorFrame) self.masterSelectorLabel = qt.QLabel("Master Volume: ", self.masterSelectorFrame) self.masterSelectorLabel.setToolTip( "Select the master volume (background grayscale scalar volume node)" ) self.masterSelectorFrame.layout().addWidget(self.masterSelectorLabel) self.masterSelector = slicer.qMRMLNodeComboBox( self.masterSelectorFrame) self.masterSelector.objectName = 'MasterVolumeNodeSelector' # TODO self.masterSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.masterSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", 0) self.masterSelector.selectNodeUponCreation = False self.masterSelector.addEnabled = False self.masterSelector.removeEnabled = False self.masterSelector.noneEnabled = True self.masterSelector.showHidden = False self.masterSelector.showChildNodeTypes = False self.masterSelector.setMRMLScene(slicer.mrmlScene) # TODO: need to add a QLabel # self.masterSelector.SetLabelText( "Master Volume:" ) self.masterSelector.setToolTip( "Pick the master structural volume to define the segmentation. A label volume with the with \"-label\" appended to the name will be created if it doesn't already exist." ) self.masterSelectorFrame.layout().addWidget(self.masterSelector) # # merge label name and set button # self.mergeFrame = qt.QFrame(self.masterFrame) self.mergeFrame.objectName = 'MergeVolumeFrame' self.mergeFrame.setLayout(qt.QHBoxLayout()) self.masterFrame.layout().addWidget(self.mergeFrame) mergeNameToolTip = "Composite label map containing the merged structures (be aware that merge operations will overwrite any edits applied to this volume)" self.mergeNameLabel = qt.QLabel("Merge Volume: ", self.mergeFrame) self.mergeNameLabel.setToolTip(mergeNameToolTip) self.mergeFrame.layout().addWidget(self.mergeNameLabel) self.mergeName = qt.QLabel("", self.mergeFrame) self.mergeName.setToolTip(mergeNameToolTip) self.mergeFrame.layout().addWidget(self.mergeName) self.setMergeButton = qt.QPushButton("Set...", self.mergeFrame) self.setMergeButton.objectName = 'MergeVolumeButton' self.setMergeButton.setToolTip( "Set the merge volume to use with this master.") self.mergeFrame.layout().addWidget(self.setMergeButton) # # Structures Frame # self.structuresFrame = ctk.ctkCollapsibleGroupBox(self.masterFrame) self.structuresFrame.objectName = 'PerStructureVolumesFrame' self.structuresFrame.title = "Per-Structure Volumes" self.structuresFrame.collapsed = True self.structuresFrame.setLayout(qt.QVBoxLayout()) self.masterFrame.layout().addWidget(self.structuresFrame) # buttons frame self.structureButtonsFrame = qt.QFrame(self.structuresFrame) self.structureButtonsFrame.objectName = 'ButtonsFrame' self.structureButtonsFrame.setLayout(qt.QHBoxLayout()) self.structuresFrame.layout().addWidget(self.structureButtonsFrame) # add button self.addStructureButton = qt.QPushButton("Add Structure", self.structureButtonsFrame) self.addStructureButton.objectName = 'AddStructureButton' self.addStructureButton.setToolTip( "Add a label volume for a structure to edit") self.structureButtonsFrame.layout().addWidget(self.addStructureButton) # split button self.splitButton = qt.QPushButton("Split Merge Volume", self.structuresFrame) self.splitButton.objectName = 'SplitStructureButton' self.splitButton.setToolTip( "Split distinct labels from merge volume into new volumes") self.structureButtonsFrame.layout().addWidget(self.splitButton) # structures view self.structuresView = qt.QTreeView() self.structuresView.objectName = 'StructuresView' self.structuresView.sortingEnabled = True self.structuresFrame.layout().addWidget(self.structuresView) # all buttons frame self.allButtonsFrame = qt.QFrame(self.structuresFrame) self.allButtonsFrame.objectName = 'AllButtonsFrameButton' self.allButtonsFrame.setLayout(qt.QHBoxLayout()) self.structuresFrame.layout().addWidget(self.allButtonsFrame) # delete structures button self.deleteStructuresButton = qt.QPushButton("Delete Structures", self.allButtonsFrame) self.deleteStructuresButton.objectName = 'DeleteStructureButton' self.deleteStructuresButton.setToolTip( "Delete all the structure volumes from the scene.\n\nNote: to delete individual structure volumes, use the Data Module." ) self.allButtonsFrame.layout().addWidget(self.deleteStructuresButton) # merge button self.mergeButton = qt.QPushButton("Merge All", self.allButtonsFrame) self.mergeButton.objectName = 'MergeAllStructuresButton' self.mergeButton.setToolTip("Merge all structures into Merge Volume") self.allButtonsFrame.layout().addWidget(self.mergeButton) # merge and build button self.mergeAndBuildButton = qt.QPushButton("Merge And Build", self.allButtonsFrame) self.mergeAndBuildButton.objectName = 'MergeStructuresAndBuildModelsButton' self.mergeAndBuildButton.setToolTip( "Merge all structures into Merge Volume and build models from all structures" ) self.allButtonsFrame.layout().addWidget(self.mergeAndBuildButton) # options frame self.optionsFrame = qt.QFrame(self.structuresFrame) self.optionsFrame.objectName = 'OptionsFrame' self.optionsFrame.setLayout(qt.QHBoxLayout()) self.structuresFrame.layout().addWidget(self.optionsFrame) # replace models button self.replaceModels = qt.QCheckBox("Replace Models", self.optionsFrame) self.replaceModels.objectName = 'ReplaceModelsCheckBox' self.replaceModels.setToolTip( "Replace any existing models when building") self.replaceModels.setChecked(1) self.optionsFrame.layout().addWidget(self.replaceModels) # # signals, slots, and observers # # signals/slots on qt widgets are automatically when # this class destructs, but observers of the scene must be explicitly # removed in the destuctor # node selected self.masterSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.onSelect) # buttons pressed self.addStructureButton.connect("clicked()", self.addStructure) self.deleteStructuresButton.connect("clicked()", self.deleteStructures) # selection changed event # invoked event self.splitButton.connect("clicked()", self.split) self.mergeButton.connect("clicked()", self.mergeStructures) self.mergeAndBuildButton.connect("clicked()", self.onMergeAndBuild) self.setMergeButton.connect("clicked()", self.labelSelectDialog) # so buttons will initially be disabled self.master = None self.updateStructures()
def setup(self): # Instantiate and connect widgets ... # # Reload and Test area # reloadCollapsibleButton = ctk.ctkCollapsibleButton() reloadCollapsibleButton.text = "Reload && Test" self.layout.addWidget(reloadCollapsibleButton) reloadFormLayout = qt.QFormLayout(reloadCollapsibleButton) # reload button # (use this during development, but remove it when delivering # your module to users) self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "NeurosurgicalPlanningTutorialMarkupsSelfTest Reload" reloadFormLayout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # reload and test button # (use this during development, but remove it when delivering # your module to users) self.reloadAndTestButton = qt.QPushButton("Reload and Test") self.reloadAndTestButton.toolTip = "Reload this module and then run the self tests." reloadFormLayout.addWidget(self.reloadAndTestButton) self.reloadAndTestButton.connect('clicked()', self.onReloadAndTest) # # Parameters Area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Parameters" self.layout.addWidget(parametersCollapsibleButton) # Layout within the dummy collapsible button parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) # # check box to trigger taking screen shots for later use in tutorials # self.enableScreenshotsFlagCheckBox = qt.QCheckBox() self.enableScreenshotsFlagCheckBox.checked = 0 self.enableScreenshotsFlagCheckBox.setToolTip( "If checked, take screen shots for tutorials. Use Save Data to write them to disk." ) parametersFormLayout.addRow("Enable Screenshots", self.enableScreenshotsFlagCheckBox) # # scale factor for screen shots # self.screenshotScaleFactorSliderWidget = ctk.ctkSliderWidget() self.screenshotScaleFactorSliderWidget.singleStep = 1.0 self.screenshotScaleFactorSliderWidget.minimum = 1.0 self.screenshotScaleFactorSliderWidget.maximum = 50.0 self.screenshotScaleFactorSliderWidget.value = 1.0 self.screenshotScaleFactorSliderWidget.setToolTip( "Set scale factor for the screen shots.") parametersFormLayout.addRow("Screenshot scale factor", self.screenshotScaleFactorSliderWidget) # Apply Button # self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Run the algorithm." self.applyButton.enabled = True parametersFormLayout.addRow(self.applyButton) # connections self.applyButton.connect('clicked(bool)', self.onApplyButton) # Add vertical spacer self.layout.addStretch(1)
def create(self, widgetType='window', showHeader=False, showPreview=False): """ main window is a frame with widgets from the app widget repacked into it along with slicer-specific extra widgets """ # find internals of widget for reference and repacking self.toolBar = slicer.util.findChildren(self.dicomApp, 'ToolBar')[0] self.databaseNameLabel = slicer.util.findChildren( self.dicomApp, 'DatabaseNameLabel')[0] self.databaseDirectoryButton = slicer.util.findChildren( self.dicomApp, 'DirectoryButton')[0] self.tree = slicer.util.findChildren(self.dicomApp, 'TreeView')[0] self.userFrame = slicer.util.findChildren(self.dicomApp, 'UserFrame')[0] self.thumbs = slicer.util.findChildren(self.dicomApp, 'ThumbnailsWidget')[0] self.widthSlider = slicer.util.findChildren(self.dicomApp, 'ThumbnailWidthSlider')[0] self.preview = slicer.util.findChildren(self.dicomApp, 'PreviewFrame')[0] self.widgetType = widgetType if widgetType == 'dialog': self.window = qt.QDialog(self.dicomApp) elif widgetType == 'window': self.window = qt.QWidget() elif widgetType == 'popup': self.window = ctk.ctkPopupWidget(self.dicomApp) self.window.orientation = 1 self.window.horizontalDirection = 0 self.window.alignment = 0x82 elif widgetType == 'dock': self.dock = qt.QDockWidget(slicer.util.mainWindow()) self.dock.setFeatures(qt.QDockWidget.DockWidgetFloatable | qt.QDockWidget.DockWidgetMovable | qt.QDockWidget.DockWidgetClosable) slicer.util.mainWindow().addDockWidget(0x15, self.dock) self.window = qt.QFrame() self.dock.setWidget(self.window) else: raise "Unknown widget type - should be dialog, window, dock or popup" self.window.setWindowTitle('DICOM Details') self.layout = qt.QGridLayout() self.window.setLayout(self.layout) # overall layout - tree on top, preview and selection below toolRow = 0 treeRow = 1 selectionRow = 2 # tool row at top, with commands and database self.toolLayout = qt.QHBoxLayout() self.layout.addLayout(self.toolLayout, toolRow, 0, 1, 2) self.toolLayout.addWidget(self.toolBar) self.toolLayout.addWidget(self.databaseNameLabel) self.toolLayout.addWidget(self.databaseDirectoryButton) # tree goes next, spread across 1 row, 2 columns self.layout.addWidget(self.tree, treeRow, 0, 1, 2) # # preview related column # self.previewLayout = qt.QVBoxLayout() self.layout.addLayout(self.previewLayout, selectionRow, 0) self.previewLayout.addWidget(self.thumbs) self.previewLayout.addWidget(self.widthSlider) if showPreview: self.previewLayout.addWidget(self.preview) else: self.preview.hide() # # action related column (interacting with slicer) # self.actionLayout = qt.QVBoxLayout() self.layout.addLayout(self.actionLayout, selectionRow, 1) self.actionLayout.addWidget(self.userFrame) tableWidth = 350 if showHeader else 700 self.loadableTable = DICOMLoadableTable(self.userFrame, width=tableWidth) self.actionLayout.addWidget(self.loadableTable.widget) # # button row for action column # self.actionButtonLayout = qt.QHBoxLayout() self.actionLayout.addLayout(self.actionButtonLayout) self.uncheckAllButton = qt.QPushButton('Uncheck All') self.actionButtonLayout.addWidget(self.uncheckAllButton) self.uncheckAllButton.connect('clicked()', self.uncheckAllLoadables) self.loadButton = qt.QPushButton('Load Selection to Slicer') self.loadButton.enabled = False self.actionButtonLayout.addWidget(self.loadButton) self.loadButton.connect('clicked()', self.loadCheckedLoadables) self.closeButton = qt.QPushButton('Close') self.actionButtonLayout.addWidget(self.closeButton) self.closeButton.connect('clicked()', self.close) if self.setBrowserPersistence: self.browserPersistentButton = qt.QCheckBox( 'Make DICOM Browser Persistent') self.browserPersistentButton.toolTip = 'When enabled, DICOM Broswer remains open and usable after leaving DICOM module' self.actionLayout.addWidget(self.browserPersistentButton) self.browserPersistentButton.connect('stateChanged(int)', self.setBrowserPersistence) # # header related column (more details about the selected file) # if showHeader: self.headerLayout = qt.QVBoxLayout() self.layout.addLayout(self.headerLayout, selectionRow, 2) self.header = DICOMHeaderWidget(self.window) self.headerLayout.addWidget(self.header.widget)
def setup(self): """Init the widget """ # ScriptedLoadableModuleWidget.setup(self) settings = qt.QSettings() if (SlicerUtil.IsDevelopment): # reload button self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "Reload" self.layout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onBtnReloadClicked) self.logic = PicasaSnapLogic() self.__addObservers__() ######## Credentials self.credentialsCollapsibleButton = ctk.ctkCollapsibleButton() self.credentialsCollapsibleButton.text = "Credentials" self.layout.addWidget(self.credentialsCollapsibleButton) self.credentialsLayout = qt.QFormLayout(self.credentialsCollapsibleButton) self.isUserLogged = False self.loginLineEdit = qt.QLineEdit() self.credentialsLayout.addRow("Login: "******"Password: "******"Remember my credentials") self.rememberCredentialsCheckBox.toolTip = "Check for an automatic login when the application starts" self.loginButton = qt.QPushButton("Login") self.loginButton.toolTip = "Login in Picassa service (Google credentials)" self.logoutButton = qt.QPushButton("Logout") self.logoutButton.toolTip = "Logout to connect with another user's credentials" # Add all the items, they will be shown/hidden in refreshCredentialsUI function self.credentialsLayout.addRow(self.rememberCredentialsCheckBox, self.loginButton) self.credentialsLayout.addRow(None, self.logoutButton) ######## Snapshots (main frame) self.mainCollapsibleButton = ctk.ctkCollapsibleButton() self.mainCollapsibleButton.text = "Snapshots" self.layout.addWidget(self.mainCollapsibleButton) self.mainLayout = qt.QVBoxLayout(self.mainCollapsibleButton) ############### Current snapshots self.currentSnapshotsFrame = qt.QFrame() self.currentSnapshotsLayout = qt.QVBoxLayout() self.currentSnapshotsFrame.setLayout(self.currentSnapshotsLayout) self.currentSnapshotsFrame.setFrameShape(qt.QFrame.StyledPanel) self.mainLayout.addWidget(self.currentSnapshotsFrame) self.snapshotsLabel = qt.QLabel("Snapshots to upload:") self.snapshotsLabel.setStyleSheet("font-weight:bold; font-size:14px; margin-bottom:10px") self.currentSnapshotsLayout.addWidget(self.snapshotsLabel) # Subframe that contains the checkbox list self.currentSnapshotsInnerFrame = qt.QFrame() self.currentSnapshotsInnerLayout = qt.QVBoxLayout() self.currentSnapshotsInnerFrame.setLayout(self.currentSnapshotsInnerLayout) self.currentSnapshotsLayout.addWidget(self.currentSnapshotsInnerFrame) self.noItemsLabel = qt.QLabel("(There are not any snapshots at the moment)") # Add the label by default. It will be hidden if there is any snapshot self.currentSnapshotsInnerLayout.addWidget(self.noItemsLabel) self.loadExistingSnapshotsFirstLoad() ############### Albums # Try to login before getting the albums self.login() msgBox = None if self.isUserLogged: # Show message box while loading the data msgBox = qt.QMessageBox(qt.QMessageBox.Information, 'Login','Connecting with Picasa. Please wait...', qt.QMessageBox.Cancel) msgBox.show() try: self.albumNameFrame = qt.QFrame() self.albumNameLayout = qt.QHBoxLayout() self.albumNameFrame.setLayout(self.albumNameLayout) self.albumNameFrame.setFrameShape(qt.QFrame.StyledPanel) self.albumNameLabel = qt.QLabel("Album name:") self.albumNameLabel.setStyleSheet("font-weight:bold;") self.albumNamesComboBox = qt.QComboBox() self.loadAlbums() self.albumNameLayout.addWidget(self.albumNameLabel) self.albumNameLayout.addWidget(self.albumNamesComboBox) self.mainLayout.addWidget(self.albumNameFrame) ############### Tags self.tagsFrame = qt.QFrame() self.tagsLayout = qt.QGridLayout() self.tagsFrame.setLayout(self.tagsLayout) self.tagsFrame.setFrameShape(qt.QFrame.StyledPanel) self.tagsLabel = qt.QLabel("Tags (select all that apply, you can filter o create new tags):") self.tagsLabel.setStyleSheet("font-weight: bold; margin-bottom: 10px; margin-top: 5px") self.tagsLayout.addWidget(self.tagsLabel, 0, 0, 1, 3) # Add input to filter tags and button to add a new one self.tagsFilterLineEdit = qt.QLineEdit() self.tagsFilterLineEdit.toolTip = "Type here to filter your tags. If you press the return key all the visible tags will be checked" #self.tagsFilterLineEdit.setStyleSheet(style) self.tagsLayout.addWidget(self.tagsFilterLineEdit, 1, 0, 1, 2) self.newTagButton = qt.QPushButton("New tag") #self.newTagButton.setStyleSheet("background-color: #5D74C6; color:white") self.newTagButton.setIconSize(qt.QSize(20,20)) self.newTagButton.setIcon(qt.QIcon(self.CIP_ICON_DIR + "/Plus - 48.png")) self.newTagButton.setFixedWidth(75) self.newTagButton.toolTip = "Add a new tag (the tag will not be created until you upload any picture with it)" self.tagsLayout.addWidget(self.newTagButton, 1, 2) self.loadTags() ############### Upload snapshots controls self.uploadSnapsButtonFrame = qt.QFrame() self.uploadSnapsLayout = qt.QHBoxLayout() self.uploadSnapsButtonFrame.setLayout(self.uploadSnapsLayout) #self(qt.QFrame.HLine) self.mainLayout.addWidget(self.uploadSnapsButtonFrame) self.uploadSnapshotsButton = qt.QPushButton() self.uploadSnapshotsButton.text = "Upload to Picasa!" self.uploadSnapshotsButton.toolTip = "Upload selected screenshots to Picassa" self.uploadSnapshotsButton.setStyleSheet("background-color: #5D74C6; color: white; font-weight: bold; font-size:14px") self.uploadSnapshotsButton.setIcon(qt.QIcon(self.CIP_ICON_DIR + "/Upload - 64.png")) self.uploadSnapshotsButton.setIconSize(qt.QSize(24,24)) self.uploadSnapshotsButton.setFixedSize(170, 35) self.uploadSnapsLayout.addWidget(self.uploadSnapshotsButton) ############### Progress bar self.progressBar = qt.QProgressDialog() self.progressBar.setMinimum(0) self.progressBar.setMinimumDuration(0) self.progressBar.setWindowModality(True) # Check for updates in CIP #autoUpdate = SlicerUtil.settingGetOrSetDefault("PicasaSnap", "AutoUpdate", 1) #uw = AutoUpdateWidget(parent=self.parent, autoUpdate=autoUpdate) #uw.addAutoUpdateCheckObserver(self.onAutoUpdateStateChanged) # self.uploadProgressFrame = qt.QFrame() # self.uploadProgressLayout = qt.QVBoxLayout() # self.uploadProgressFrame.setLayout(self.uploadProgressLayout) # # # Gif image # self.imUploading = qt.QMovie("%s/loading.gif" % self.CIP_ICON_DIR, qt.QByteArray()) # # Label to contain the gif # self.lblImLoading = qt.QLabel() # # Fix the dimensions of the image (by fixing the dimensions of the label that contains it) # self.lblImLoading.setFixedWidth(40) # # Other image parameters # self.imUploading.setCacheMode(qt.QMovie.CacheAll) # self.imUploading.setSpeed(100) # # Assign the label to the image (don't start it yet, it will be started when we are uploading) # self.lblImLoading.setMovie(self.imUploading) # #self.imUploading.start() # self.uploadProgressLayout.addWidget(self.lblImLoading) # # # Label that will show the progress # self.lblUploading = qt.QLabel("Uploading %i/%i images...") # self.uploadProgressLayout.addWidget(self.lblUploading) # # Cancel uploading button # self.btnCancelUpload = qt.QPushButton("Cancel") # self.btnCancelUpload.toolTip = "Cancel the process" # self.btnCancelUpload.setFixedWidth(100) # self.uploadProgressLayout.addWidget(self.btnCancelUpload) # self.mainLayout.addWidget(self.uploadProgressFrame) # # # Hide the progress frame # self.uploadProgressFrame.hide() ######## Connections self.uploadSnapshotsButton.connect('clicked (bool)', self.onUploadSnapshotsButtonClicked) self.loginButton.connect('clicked (bool)', self.onLoginButtonClicked) self.logoutButton.connect('clicked (bool)', self.onLogoutButtonClicked) self.loginLineEdit.returnPressed.connect(self.onLoginPasswordReturnKeyPressed) self.passwordLineEdit.returnPressed.connect(self.onLoginPasswordReturnKeyPressed) self.albumNamesComboBox.connect("currentIndexChanged (int)", self.onAlbumsCurrentIndexChanged) self.newTagButton.connect('clicked (bool)', self.onNewTagButtonClicked) self.tagsFilterLineEdit.connect('textEdited (QString)', self.onFilterTagsEdited) self.tagsFilterLineEdit.returnPressed.connect(self.onFilterTagsReturnKeyPressed) # Add vertical spacer self.layout.addStretch(1) finally: # Hide MesageBox if it was visible if msgBox: msgBox.close()
def createUserInterface(self): self.__layout = self.__parent.createUserInterface() self.__previewWindow = ctk.ctkVTKSliceView() self.__previewHLayout = qt.QHBoxLayout() self.__previewHLayout.addWidget(self.__previewWindow) self.__spaceLabel = qt.QLabel(" ") self.__previewHLayout.addWidget(self.__spaceLabel) self.__spaceLabel2 = qt.QLabel(" ") self.__previewHLayout.addWidget(self.__spaceLabel2) self.__layout.addRow(self.__previewHLayout) # Frame slider # self.frameSlider = ctk.ctkSliderWidget() # frameSlider.connect('valueChanged(double)', self.frameSliderValueChanged) # self.frameSlider.decimals = 0 # self.__layout.addRow("Preview for one Slicer: ", self.frameSlider) self.__ioAdvancedToggle = qt.QCheckBox("Show Advanced") self.__ioAdvancedToggle.setChecked(False) self.__layout.addRow(self.__ioAdvancedToggle) # # I/O advanced panel # self.__ioAdvancedPanel = qt.QFrame(self) self.__ioAdvancedPanel.hide() print "testss" self.__ioAdvancedPanel.setFrameStyle(6) self.__layout.addRow(self.__ioAdvancedPanel) self.__ioAdvancedToggle.connect("clicked()", self.onIOAdvancedToggle) ioAdvancedFormLayout = qt.QFormLayout(self.__ioAdvancedPanel) # Frame delay slider self.frameDelaySlider = ctk.ctkRangeWidget() # frameDelaySlider.connect('valueChanged(double)', self.frameDelaySliderValueChanged) self.frameDelaySlider.decimals = 0 self.frameDelaySlider.minimum = 1 self.frameDelaySlider.maximum = 70 self.frameDelaySlider.minimumValue = 5 self.frameDelaySlider.maximumValue = 20 self.frameDelaySlider.suffix = " vx" # self.frameDelaySlider.value = 20 ioAdvancedFormLayout.addRow("Diameters [Min-Max]: ", self.frameDelaySlider) # Frame delay slider self.frameDelaySlider = ctk.ctkSliderWidget() # frameDelaySlider.connect('valueChanged(double)', self.frameDelaySliderValueChanged) self.frameDelaySlider.decimals = 0 self.frameDelaySlider.minimum = 5 self.frameDelaySlider.maximum = 100 self.frameDelaySlider.value = 20 ioAdvancedFormLayout.addRow("Input Contrast: ", self.frameDelaySlider) self.__previewButton = qt.QPushButton() self.__previewButton.text = "Update preview" # self.__inputVolumeNodeSelector.setMRMLScene(slicer.mrmlScene) self.__previewButtonHLayout = qt.QHBoxLayout() self.__spaceLabel2 = qt.QLabel(" ") self.__previewButtonHLayout.addWidget(self.__spaceLabel2) self.__spaceLabel = qt.QLabel(" ") self.__previewButtonHLayout.addWidget(self.__spaceLabel) self.__previewButtonHLayout.addWidget(self.__previewButton) self.__layout.addRow(self.__previewButtonHLayout) self.__previewButton.connect("clicked()", self.updatePreview)
def setup(self): # # the grayscale volume selector # self.grayscaleSelectorFrame = qt.QFrame(self.parent) self.grayscaleSelectorFrame.setLayout(qt.QHBoxLayout()) self.parent.layout().addWidget(self.grayscaleSelectorFrame) self.grayscaleSelectorLabel = qt.QLabel("Grayscale Volume: ", self.grayscaleSelectorFrame) self.grayscaleSelectorLabel.setToolTip( "Select the grayscale volume (background grayscale scalar volume node) for statistics calculations" ) self.grayscaleSelectorFrame.layout().addWidget( self.grayscaleSelectorLabel) self.grayscaleSelector = slicer.qMRMLNodeComboBox( self.grayscaleSelectorFrame) self.grayscaleSelector.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.grayscaleSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", 0) self.grayscaleSelector.selectNodeUponCreation = False self.grayscaleSelector.addEnabled = False self.grayscaleSelector.removeEnabled = False self.grayscaleSelector.noneEnabled = True self.grayscaleSelector.showHidden = False self.grayscaleSelector.showChildNodeTypes = False self.grayscaleSelector.setMRMLScene(slicer.mrmlScene) # TODO: need to add a QLabel # self.grayscaleSelector.SetLabelText( "Master Volume:" ) self.grayscaleSelectorFrame.layout().addWidget(self.grayscaleSelector) # # the label volume selector # self.labelSelectorFrame = qt.QFrame() self.labelSelectorFrame.setLayout(qt.QHBoxLayout()) self.parent.layout().addWidget(self.labelSelectorFrame) self.labelSelectorLabel = qt.QLabel() self.labelSelectorLabel.setText("Label Map: ") self.labelSelectorFrame.layout().addWidget(self.labelSelectorLabel) self.labelSelector = slicer.qMRMLNodeComboBox() self.labelSelector.nodeTypes = ("vtkMRMLScalarVolumeNode", "") self.labelSelector.addAttribute("vtkMRMLScalarVolumeNode", "LabelMap", "1") # todo addAttribute self.labelSelector.selectNodeUponCreation = False self.labelSelector.addEnabled = False self.labelSelector.noneEnabled = True self.labelSelector.removeEnabled = False self.labelSelector.showHidden = False self.labelSelector.showChildNodeTypes = False self.labelSelector.setMRMLScene(slicer.mrmlScene) self.labelSelector.setToolTip("Pick the label map to edit") self.labelSelectorFrame.layout().addWidget(self.labelSelector) # Apply button self.applyButton = qt.QPushButton("Apply") self.applyButton.toolTip = "Calculate Statistics." self.applyButton.enabled = False self.parent.layout().addWidget(self.applyButton) # model and view for stats table self.view = qt.QTableView() self.view.sortingEnabled = True self.parent.layout().addWidget(self.view) # Chart button self.chartFrame = qt.QFrame() self.chartFrame.setLayout(qt.QHBoxLayout()) self.parent.layout().addWidget(self.chartFrame) self.chartButton = qt.QPushButton("Chart") self.chartButton.toolTip = "Make a chart from the current statistics." self.chartFrame.layout().addWidget(self.chartButton) self.chartOption = qt.QComboBox() self.chartOption.addItems(self.chartOptions) self.chartFrame.layout().addWidget(self.chartOption) self.chartIgnoreZero = qt.QCheckBox() self.chartIgnoreZero.setText('Ignore Zero') self.chartIgnoreZero.checked = False self.chartIgnoreZero.setToolTip( 'Do not include the zero index in the chart to avoid dwarfing other bars' ) self.chartFrame.layout().addWidget(self.chartIgnoreZero) self.chartFrame.enabled = False # Save button self.saveButton = qt.QPushButton("Save") self.saveButton.toolTip = "Calculate Statistics." self.saveButton.enabled = False self.parent.layout().addWidget(self.saveButton) # Add vertical spacer self.parent.layout().addStretch(1) # connections self.applyButton.connect('clicked()', self.onApply) self.chartButton.connect('clicked()', self.onChart) self.saveButton.connect('clicked()', self.onSave) self.grayscaleSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onGrayscaleSelect) self.labelSelector.connect('currentNodeChanged(vtkMRMLNode*)', self.onLabelSelect)
def setup(self): """This is called one time when the module GUI is initialized """ # Declare ALL the GUI components (depending on the context we will add different ones to the layout) self.widgetMainFrame = qt.QFrame() self.widgetMainLayout = qt.QGridLayout() self.widgetMainFrame.setLayout(self.widgetMainLayout) self.layout.addWidget(self.widgetMainFrame) ## Context self.contextLabel = qt.QLabel("Context") self.contextComboBox = qt.QComboBox() for context in self.contexts.itervalues(): self.contextComboBox.addItem(context) ## Operation self.operationLabel = qt.QLabel("Optimization") self.operationComboBox = qt.QComboBox() for operation in self.operations.itervalues(): if operation != self.OPERATION_NONE: self.operationComboBox.addItem(operation) ## Plane self.planeLabel = qt.QLabel("Plane") # Buttons group self.planesButtonGroup = qt.QButtonGroup() # Axial self.axialButton = qt.QPushButton() self.axialButton.setCheckable(True) self.axialButton.toolTip = "Axial plane" self.axialButton.setFixedSize(40, 40) self.axialButton.setIcon(SlicerUtil.getIcon("axial.png")) self.planesButtonGroup.addButton(self.axialButton, self.PLANE_AXIAL) # Sagittal self.sagittalButton = qt.QPushButton() self.sagittalButton.setCheckable(True) self.sagittalButton.toolTip = "Sagittal plane" self.sagittalButton.setFixedSize(40, 40) self.sagittalButton.setIcon(SlicerUtil.getIcon("sagittal.png")) self.widgetMainLayout.addWidget(self.sagittalButton, 2, 2, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.planesButtonGroup.addButton(self.sagittalButton, self.PLANE_SAGITTAL) # Coronal self.coronalButton = qt.QPushButton() self.coronalButton.setCheckable(True) self.coronalButton.toolTip = "coronal plane" self.coronalButton.setFixedSize(40, 40) self.coronalButton.setIcon(SlicerUtil.getIcon("coronal.png")) self.planesButtonGroup.addButton(self.coronalButton, self.PLANE_CORONAL) # Null button (to uncheck all) self.nullPlaneButton = qt.QPushButton() self.nullPlaneButton.setCheckable(True) self.planesButtonGroup.addButton(self.nullPlaneButton, -1) # Buttons labels self.axialButtonLabel = qt.QLabel("Axial") self.axialButtonLabel.setStyleSheet("margin-bottom: 10px") self.sagittalButtonLabel = qt.QLabel("Sagittal") self.sagittalButtonLabel.setStyleSheet("margin-bottom: 10px") self.coronalButtonLabel = qt.QLabel("Coronal") self.coronalButtonLabel.setStyleSheet("margin-bottom: 10px") ## Layout self.layoutLabel = qt.QLabel("Layout") # Buttons group self.layoutsButtonGroup = qt.QButtonGroup() # Single slice Button self.singleSlideViewButton = qt.QPushButton() self.singleSlideViewButton.setCheckable(True) self.singleSlideViewButton.toolTip = "Single slice view" self.singleSlideViewButton.setFixedSize(40, 40) self.singleSlideViewButton.setIcon( qt.QIcon(":/Icons/LayoutOneUpRedSliceView.png")) self.layoutsButtonGroup.addButton(self.singleSlideViewButton, self.LAYOUT_RED_ONLY) # Side by side Button self.sideBySideViewButton = qt.QPushButton() self.sideBySideViewButton.setCheckable(True) self.sideBySideViewButton.toolTip = "Side by side view" self.sideBySideViewButton.setFixedSize(40, 40) self.sideBySideViewButton.setIcon( qt.QIcon(":/Icons/LayoutSideBySideView.png")) self.layoutsButtonGroup.addButton(self.sideBySideViewButton, self.LAYOUT_SIDE_BY_SIDE) # Three over three button self.threeOverThreeViewButton = qt.QPushButton() self.threeOverThreeViewButton.setCheckable(True) self.threeOverThreeViewButton.toolTip = "Compare 2 images in their 3 planes" self.threeOverThreeViewButton.setFixedSize(40, 40) self.threeOverThreeViewButton.setIcon( qt.QIcon(":/Icons/LayoutThreeOverThreeView.png")) self.layoutsButtonGroup.addButton(self.threeOverThreeViewButton, self.LAYOUT_THREE_OVER_THREE) # Comparative MIP-MinIP button self.maxMinCompareViewButton = qt.QPushButton() self.maxMinCompareViewButton.setCheckable(True) self.maxMinCompareViewButton.toolTip = "MIP and MinIP comparison" self.maxMinCompareViewButton.setFixedSize(40, 40) self.maxMinCompareViewButton.setIcon( qt.QIcon(":/Icons/LayoutFourUpView.png")) self.layoutsButtonGroup.addButton(self.maxMinCompareViewButton, self.LAYOUT_COMPARE) # Null button (to uncheck all) self.nullLayoutButton = qt.QPushButton() self.nullLayoutButton.setCheckable(True) self.layoutsButtonGroup.addButton(self.nullLayoutButton, -2) # Reset Button self.resetViewButton = qt.QPushButton() self.resetViewButton.toolTip = "Go back to the original layout" self.resetViewButton.setFixedSize(40, 40) # self.resetViewButton.setIconSize(qt.QSize(24, 24)) self.resetViewButton.setIcon( qt.QIcon(os.path.join(SlicerUtil.CIP_ICON_DIR, "Reload.png"))) # Buttons labels self.singleSlideButtonLabel = qt.QLabel("Single") self.sideBySideButtonLabel = qt.QLabel("Side by side") self.threeOverThreeButtonLabel = qt.QLabel("3x3") self.maxMinCompareButtonLabel = qt.QLabel("MIP+MinIP") self.resetLabel = qt.QLabel("Reset") self.resetLabel.setStyleSheet("font-weight: bold") # Number of slices (different for each operation). The size of the slider also changes self.spacingSliderItems = OrderedDict() spacingLabel = qt.QLabel("Slice size " + self.operations[self.OPERATION_MIP]) spacingSlider = qt.QSlider() spacingSlider.orientation = 1 spacingSlider.setTickPosition(2) spacingSlider.minimum = 0 spacingSlider.maximum = 1000 spacingSlider.setPageStep(50) spacingMmLabel = qt.QLabel() self.spacingSliderItems[self.OPERATION_MIP] = (spacingLabel, spacingSlider, spacingMmLabel) self.setCurrentSpacingInMm(self.OPERATION_MIP, 20) spacingLabel = qt.QLabel("Slice size " + self.operations[self.OPERATION_MinIP]) spacingSlider = qt.QSlider() spacingSlider.orientation = 1 spacingSlider.setTickPosition(2) spacingSlider.minimum = 0 spacingSlider.maximum = 200 spacingSlider.setPageStep(50) spacingMmLabel = qt.QLabel() self.spacingSliderItems[self.OPERATION_MinIP] = (spacingLabel, spacingSlider, spacingMmLabel) self.setCurrentSpacingInMm(self.OPERATION_MinIP, 5) spacingLabel = qt.QLabel("Slice size " + self.operations[self.OPERATION_MEAN]) spacingSlider = qt.QSlider() spacingSlider.orientation = 1 spacingSlider.setTickPosition(2) spacingSlider.minimum = 0 spacingSlider.maximum = 200 spacingSlider.setPageStep(50) spacingMmLabel = qt.QLabel() self.spacingSliderItems[self.OPERATION_MEAN] = (spacingLabel, spacingSlider, spacingMmLabel) self.setCurrentSpacingInMm(self.OPERATION_MEAN, 20) # Crosshair self.crosshairCheckbox = qt.QCheckBox() self.crosshairCheckbox.setText("Crosshair cursor") self.crosshairCheckbox.toolTip = "Activate/Desactivate the crosshair cursor for a better visualization" self.crosshairCheckbox.setStyleSheet("margin-top:10px") # Center button self.centerButton = qt.QPushButton() self.centerButton.setText("Center volumes") self.centerButton.setFixedSize(100, 40) self.centerButton.setStyleSheet("margin-top:10px") if self.fullModeOn: ###### FULL MODE # Context self.widgetMainLayout.addWidget(self.contextLabel, 0, 0) self.widgetMainLayout.addWidget(self.contextComboBox, 0, 1, 1, 3) # Operation self.widgetMainLayout.addWidget(self.operationLabel, 1, 0) self.widgetMainLayout.addWidget(self.operationComboBox, 1, 1, 1, 3) # Plane self.widgetMainLayout.addWidget(self.planeLabel, 2, 0) self.widgetMainLayout.addWidget( self.axialButton, 2, 1, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.coronalButton, 2, 3, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.axialButtonLabel, 3, 1, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.sagittalButtonLabel, 3, 2, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.coronalButtonLabel, 3, 3, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) # Layout self.widgetMainLayout.addWidget(self.layoutLabel, 4, 0) self.widgetMainLayout.addWidget( self.singleSlideViewButton, 4, 1, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.sideBySideViewButton, 4, 2, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.threeOverThreeViewButton, 4, 3, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.maxMinCompareViewButton, 4, 4, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.resetViewButton, 4, 5, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.singleSlideButtonLabel, 5, 1, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.sideBySideButtonLabel, 5, 2, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.threeOverThreeButtonLabel, 5, 3, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.maxMinCompareButtonLabel, 5, 4, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.resetLabel, 5, 5, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) # Number of slices row = 6 for structure in self.spacingSliderItems.itervalues(): self.widgetMainLayout.addWidget(structure[0], row, 0, 1, 2) self.widgetMainLayout.addWidget(structure[1], row, 2, 1, 3) self.widgetMainLayout.addWidget(structure[2], row, 5) row += 1 self.widgetMainLayout.addWidget(self.crosshairCheckbox, row, 0, 1, 2) self.crosshairCheckbox.setChecked(True) self.widgetMainLayout.addWidget(self.centerButton, row, 2, 1, 2) else: ##### COLLAPSED MODE # Plane self.widgetMainLayout.addWidget(self.planeLabel, 0, 0) self.widgetMainLayout.addWidget( self.axialButton, 0, 1, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.sagittalButton, 0, 2, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.coronalButton, 0, 3, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.threeOverThreeViewButton, 0, 4, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.axialButtonLabel, 1, 1, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.sagittalButtonLabel, 1, 2, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.coronalButtonLabel, 1, 3, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) self.widgetMainLayout.addWidget( self.threeOverThreeButtonLabel, 1, 4, SlicerUtil.ALIGNMENT_HORIZONTAL_CENTER) # Number of slices row = 2 for structure in self.spacingSliderItems.itervalues(): self.widgetMainLayout.addWidget(structure[0], row, 0) self.widgetMainLayout.addWidget(structure[1], row, 1, 1, 3) self.widgetMainLayout.addWidget(structure[2], row, 4) row += 1 self.widgetMainLayout.addWidget(self.crosshairCheckbox, row, 0) self.widgetMainLayout.addWidget(self.centerButton, row, 1, 1, 2) self.layout.addStretch(1) self.__refreshUI__() # Connections self.contextComboBox.connect("currentIndexChanged (int)", self.__onContextIndexChanged__) self.operationComboBox.connect("currentIndexChanged (int)", self.__onOperationIndexChanged__) self.planesButtonGroup.connect("buttonClicked(int)", self.__onPlaneButtonClicked__) self.singleSlideViewButton.connect("clicked()", self.__onSingleSlideButtonClicked__) self.sideBySideViewButton.connect("clicked()", self.__onSideBySideButtonClicked__) self.threeOverThreeViewButton.connect( "clicked()", self.__onThreeOverThreeViewButtonClicked__) self.maxMinCompareViewButton.connect( "clicked()", self.__onMaxMinCompareViewButtonClicked__) self.resetViewButton.connect("clicked()", self.__onResetViewButtonClicked__) for slicer in (item[1] for item in self.spacingSliderItems.itervalues()): slicer.connect('valueChanged(int)', self.__onNumberOfSlicesChanged__) self.crosshairCheckbox.connect("stateChanged(int)", self.__onCrosshairCheckChanged__) self.centerButton.connect("clicked()", self.__onCenterButtonClicked__)
def setup(self): """Init the widget """ self.modulePath = SlicerUtil.getModuleFolder("CIP_GetImage") self.resourcesPath = os.path.join(self.modulePath, "CIP_GetImage_Resources") self.StudyId = "" self.logic = CIP_GetImageLogic(self.modulePath) # Widget to load cases faster self.loadSaveDatabuttonsWidget = CIPUI.LoadSaveDataWidget( parentWidget=self.parent) self.loadSaveDatabuttonsWidget.setup(moduleName="CIP_GetImage") # # Obligatory parameters area # parametersCollapsibleButton = ctk.ctkCollapsibleButton() parametersCollapsibleButton.text = "Image data" self.layout.addWidget(parametersCollapsibleButton) parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton) # Study radio buttons label = qt.QLabel() label.text = "Select the study:" parametersFormLayout.addRow(label) self.rbgStudy = qt.QButtonGroup() for key in self.studyIds: rbStudyid = qt.QRadioButton(key) self.rbgStudy.addButton(rbStudyid) parametersFormLayout.addWidget(rbStudyid) self.txtOtherStudy = qt.QLineEdit() self.txtOtherStudy.hide() parametersFormLayout.addWidget(self.txtOtherStudy) # Case id self.txtCaseId = qt.QLineEdit() parametersFormLayout.addRow("Case ID ", self.txtCaseId) # Image types label = qt.QLabel() label.text = "Select the images that you want to load:" parametersFormLayout.addRow(label) self.cbsImageTypes = [] for key in self.imageTypes: check = qt.QCheckBox() check.checked = True check.setText(key) parametersFormLayout.addWidget(check) self.cbsImageTypes.append(check) # Label maps label = qt.QLabel() label.text = "Select the label maps that you want to load:" parametersFormLayout.addRow(label) # Labelmap types checkboxes self.cbsLabelMapTypes = [] for key in self.labelMapTypes: check = qt.QCheckBox() check.setText(key) check.checked = self.labelMapTypes[key][0] parametersFormLayout.addWidget(check) self.cbsLabelMapTypes.append(check) # Load image Button self.downloadButton = qt.QPushButton("Download") self.downloadButton.toolTip = "Load the image" #self.downloadButton.enabled = False self.downloadButton.setStyleSheet( "background-color: green; font-weight:bold; color:white") parametersFormLayout.addRow(self.downloadButton) self.downloadButton.connect('clicked (bool)', self.onDownloadButton) # Information message self.lblDownloading = qt.QLabel() self.lblDownloading.text = "Downloading images. Please wait..." self.lblDownloading.hide() parametersFormLayout.addRow(self.lblDownloading) # # Optional Parameters # optionalParametersCollapsibleButton = ctk.ctkCollapsibleButton() optionalParametersCollapsibleButton.text = "Optional parameters" self.layout.addWidget(optionalParametersCollapsibleButton) optionalParametersFormLayout = qt.QFormLayout( optionalParametersCollapsibleButton) # Local storage (Slicer temporary path) self.localStoragePath = "{0}/CIP".format(slicer.app.temporaryPath) if not os.path.exists(self.localStoragePath): os.makedirs(self.localStoragePath) # Make sure that everybody has write permissions (sometimes there are problems because of umask) os.chmod(self.localStoragePath, 0777) self.storagePathButton = ctk.ctkDirectoryButton() self.storagePathButton.directory = self.localStoragePath optionalParametersFormLayout.addRow("Local directory: ", self.storagePathButton) # Connection type (SSH, "normal") label = qt.QLabel() label.text = "Connection type:" optionalParametersFormLayout.addRow(label) self.rbgConnectionType = qt.QButtonGroup() self.rbSSH = qt.QRadioButton("SSH (secure connection)") self.rbSSH.setChecked(True) self.rbgConnectionType.addButton(self.rbSSH) optionalParametersFormLayout.addWidget(self.rbSSH) self.rbCP = qt.QRadioButton("Common") self.rbgConnectionType.addButton(self.rbCP) optionalParametersFormLayout.addWidget(self.rbCP) # SSH Server login self.txtServer = qt.QLineEdit() s = SlicerUtil.settingGetOrSetDefault( "CIP_GetImage", "server", "This is your ssh user and server. Example: [email protected]") self.txtServer.text = s # This is your ssh user and server. Example: [email protected]" optionalParametersFormLayout.addRow("Server:", self.txtServer) # Server root path self.txtServerpath = qt.QLineEdit() s = SlicerUtil.settingGetOrSetDefault( "CIP_GetImage", "serverRootPath", "This is your root path to search for files. Ex: /Cases/Processed") self.txtServerpath.text = s # This is your root path to search for files. Ex: /Cases/Processed optionalParametersFormLayout.addRow("Server root path:", self.txtServerpath) # SSH Private key self.txtPrivateKeySSH = qt.QLineEdit() s = SlicerUtil.settingGetOrSetDefault("CIP_GetImage", "sshKey", "") self.txtPrivateKeySSH.text = s # this is the full path to your ssh key if you need it. Be aware of Unix/Windows comaptibility (hint: use os.path.join) # Please notice that you won't need a SSH key if your computer already has one locally installed" optionalParametersFormLayout.addRow( "SSH private key (leave blank for computer's default): ", self.txtPrivateKeySSH) # Cache mode self.cbCacheMode = qt.QCheckBox("Cache mode activated") self.cbCacheMode.setChecked(True) # Cache mode is activated by default optionalParametersFormLayout.addRow("", self.cbCacheMode) # Clean cache Button self.cleanCacheButton = qt.QPushButton("Clean cache") self.cleanCacheButton.toolTip = "Remove all the local cached files" optionalParametersFormLayout.addRow(self.cleanCacheButton) optionalParametersCollapsibleButton.collapsed = True if SlicerUtil.IsDevelopment: # reload button self.reloadButton = qt.QPushButton("Reload (just development)") self.reloadButton.toolTip = "Reload this module (for development purposes)." self.reloadButton.name = "Reload" self.layout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onReload) # Add vertical spacer self.layout.addStretch(1) # Connections self.rbgStudy.connect("buttonClicked (QAbstractButton*)", self.onRbStudyClicked) self.txtOtherStudy.connect("textEdited (QString)", self.onTxtOtherStudyEdited) self.rbgConnectionType.connect("buttonClicked (QAbstractButton*)", self.onRbgConnectionType) self.storagePathButton.connect("directorySelected(QString)", self.onTmpDirChanged) self.cleanCacheButton.connect('clicked (bool)', self.onCleanCacheButtonClicked)