def __init__(self, parent, dicomDatabase=None, detailsPopup=None): if dicomDatabase: self.dicomDatabase = dicomDatabase else: self.dicomDatabase = slicer.dicomDatabase self.detailsPopup = detailsPopup self.recentSeries = [] self.widget = qt.QWidget(parent) self.widget.name = 'recentActivityWidget' self.layout = qt.QVBoxLayout() self.widget.setLayout(self.layout) self.statusLabel = qt.QLabel(self.widget) self.layout.addWidget(self.statusLabel) self.statusLabel.text = 'No inserts in the past hour' self.scrollArea = qt.QScrollArea() self.layout.addWidget(self.scrollArea) self.listWidget = qt.QListWidget() self.listWidget.name = 'recentActivityListWidget' self.scrollArea.setWidget(self.listWidget) self.scrollArea.setWidgetResizable(True) self.listWidget.setProperty('SH_ItemView_ActivateItemOnSingleClick', 1) self.listWidget.connect('activated(QModelIndex)', self.onActivated) self.refreshButton = qt.QPushButton(self.widget) self.layout.addWidget(self.refreshButton) self.refreshButton.text = 'Refresh' self.refreshButton.connect('clicked()', self.update) self.tags = {} self.tags['seriesDescription'] = "0008,103e" self.tags['patientName'] = "0010,0010"
def createMainMenuDockWidget(self): # Set up main frame self.mainMenuDockWidget = qt.QDockWidget(self.parent) self.mainMenuDockWidget.setTitleBarWidget( qt.QWidget()) # hide title bar self.mainMenuDockWidget.setObjectName('FirstTaskPanel') self.mainMenuDockWidget.setWindowTitle('First Task') # self.mainMenuDockWidget.setStyleSheet(self.styleSheet) self.mainMenuDockWidget.setFeatures( qt.QDockWidget.DockWidgetMovable | qt.QDockWidget.DockWidgetFloatable) # not closable mainWindow = slicer.util.mainWindow() self.mainMenuDockWidget.setParent(mainWindow) # Setup scroll area self.mainFrame = qt.QFrame(self.mainMenuDockWidget) self.mainLayout = qt.QVBoxLayout(self.mainFrame) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.mainLayout.spacing = 0 self.mainScrollArea = qt.QScrollArea(self.mainFrame) self.mainScrollArea.widgetResizable = True self.mainScrollArea.sizeAdjustPolicy = qt.QAbstractScrollArea.AdjustToContentsOnFirstShow self.mainScrollArea.horizontalScrollBarPolicy = qt.Qt.ScrollBarAlwaysOff self.mainScrollArea.setSizePolicy( qt.QSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)) self.mainScrollArea.frameShape = qt.QFrame.NoFrame # Slicelet panel self.sliceletPanel = qt.QFrame(self.mainFrame) self.sliceletPanelLayout = qt.QVBoxLayout(self.sliceletPanel) self.sliceletPanelLayout.spacing = 0 self.mainScrollArea.setWidget(self.sliceletPanel) self.mainLayout.addWidget(self.mainScrollArea) self.mainMenuDockWidget.setWidget(self.mainFrame) # Setup feature panel self.setupUi() self.sliceletPanelLayout.addStretch(1) self.setupSettingsPanel() self.mainScrollArea.minimumWidth = self.sliceletPanel.sizeHint.width()
def remakeWidget(self): """ Ideally, this would be unncessary. But, since QScrollArea doesn't dynamically update, we have to update this ourselves. """ #------------------- # Clear all of the inner widgets #------------------- if self.innerWidget: del self.innerWidget if self.innerWidgetLayout: del self.innerWidgetLayout if self.scrollWidget: del self.scrollWidget #------------------- # Reset the inner widget layout #------------------- self.innerWidgetLayout = qt.QFormLayout() self.innerWidgetLayout.setVerticalSpacing(10) #------------------- # Sort download rows by their queue positions, # add them to the innerWidgetLayout. #------------------- sortedRows = [None] * len(self.downloadRows) for key, item in self.downloadRows.iteritems(): #print len(sortedRows), item['queuePosition'] sortedRows[item['queuePosition']] = key for key in sortedRows: self.innerWidgetLayout.addRow(self.downloadRows[key]['widget']) #------------------- # Remake the inner widget #------------------- self.innerWidget = qt.QWidget() self.innerWidget.setLayout(self.innerWidgetLayout) self.innerWidget.setObjectName('innerWidget') self.innerWidget.setStyleSheet('#innerWidget {width: 100%;}') self.innerWidget.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.MinimumExpanding) #------------------- # Remake the scroll widget #------------------- self.scrollWidget = qt.QScrollArea() self.scrollWidget.setWidget(self.innerWidget) self.scrollWidget.verticalScrollBar().setStyleSheet('width: 15px') self.scrollWidget.setObjectName('scrollWidget') self.scrollWidget.setStyleSheet('#scrollWidget {border: none}') self.scrollWidget.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.MinimumExpanding) self.scrollWidget.setWidgetResizable(True) #------------------- # Clear the master widget and add the new contents. #------------------- delWidget = self.masterLayout.itemAt(0) while (delWidget): self.masterLayout.removeItem(delWidget) del delWidget delWidget = self.masterLayout.itemAt(0) self.innerWidget.update() self.masterLayout.addRow(self.scrollWidget) self.setSizePolicy(qt.QSizePolicy.MinimumExpanding, qt.QSizePolicy.MinimumExpanding) calcHeight = (self.rowWidgetHeight + 12) * len(self.downloadRows) if calcHeight < 800: self.setMinimumHeight(calcHeight) else: self.setMinimumHeight(800) self.update()
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 = "MurineTrial 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 measurementsCollapsibleButton = ctk.ctkCollapsibleButton() measurementsCollapsibleButton.text = "Materials" self.layout.addWidget(measurementsCollapsibleButton) # Layout within the measurements collapsible button measurementsFormLayout = qt.QFormLayout(measurementsCollapsibleButton) # list of materials in the trial measurementsFormLayout.addWidget(qt.QLabel("Individual Segmentations")) self.materialsScrollArea = qt.QScrollArea() measurementsFormLayout.addWidget(self.materialsScrollArea) self.materialsListWidget = qt.QListWidget() self.materialsScrollArea.setWidget(self.materialsListWidget) self.materialsScrollArea.setWidgetResizable(True) self.materialsListWidget.setProperty( 'SH_ItemView_ActivateItemOnSingleClick', 1) self.materialsListWidget.connect('activated(QModelIndex)', self.onMaterialActivated) # populate it materialKeys = self.logic.materials.keys() materialKeys.sort() for materialKey in materialKeys: self.materialsListWidget.addItem(materialKey) # list of sampleIDs in the trial measurementsFormLayout.addWidget( qt.QLabel("Segmentation Comparisions")) self.sampleIDsScrollArea = qt.QScrollArea() measurementsFormLayout.addWidget(self.sampleIDsScrollArea) self.sampleIDsListWidget = qt.QListWidget() self.sampleIDsScrollArea.setWidget(self.sampleIDsListWidget) self.sampleIDsScrollArea.setWidgetResizable(True) self.sampleIDsListWidget.setProperty( 'SH_ItemView_ActivateItemOnSingleClick', 1) self.sampleIDsListWidget.connect('activated(QModelIndex)', self.onSampleIDActivated) # populate it for sampleID in self.logic.gigSegComparisonSampleIDs(): self.sampleIDsListWidget.addItem(sampleID) # list of retestIDs in the trial measurementsFormLayout.addWidget(qt.QLabel("Repeatability Tests")) self.retestIDsScrollArea = qt.QScrollArea() measurementsFormLayout.addWidget(self.retestIDsScrollArea) self.retestIDsListWidget = qt.QListWidget() self.retestIDsScrollArea.setWidget(self.retestIDsListWidget) self.retestIDsScrollArea.setWidgetResizable(True) self.retestIDsListWidget.setProperty( 'SH_ItemView_ActivateItemOnSingleClick', 1) self.retestIDsListWidget.connect('activated(QModelIndex)', self.onRetestActivated) # populate it for retestID in self.logic.retestComparisonSampleIDs(): self.retestIDsListWidget.addItem(retestID) # process all button processAllButton = qt.QPushButton("Process All") processAllButton.toolTip = "Loads all subjecs at all timepoints." measurementsFormLayout.addWidget(processAllButton) processAllButton.connect('clicked(bool)', self.logic.processAll) # results area self.resultsView = qt.QWebView() self.resultsView.minimumSize = qt.QSize(100, 100) policy = qt.QSizePolicy() policy.setHorizontalPolicy(qt.QSizePolicy.Ignored) self.resultsView.setSizePolicy(policy) self.layout.addWidget(self.resultsView) # Add vertical spacer self.layout.addStretch(1)
def setup(self): #Instantiate and Connect Widgets ################################################# #HeterogeneityCAD Inputs Collapsible Button self.inputHeterogeneityCADCollapsibleButton = ctk.ctkCollapsibleButton( ) self.inputHeterogeneityCADCollapsibleButton.text = "HeterogeneityCAD Input" self.layout.addWidget(self.inputHeterogeneityCADCollapsibleButton) self.inputHeterogeneityCADLayout = qt.QFormLayout( self.inputHeterogeneityCADCollapsibleButton) ##Input Volume as a PET/CT/MRI image or parameter map converted to a volume self.inputVolHetFrame = qt.QFrame( self.inputHeterogeneityCADCollapsibleButton) self.inputVolHetFrame.setLayout(qt.QHBoxLayout()) self.inputHeterogeneityCADLayout.addRow(self.inputVolHetFrame) # label for selecting individual node self.inputVolHet = qt.QLabel("Input Node: ", self.inputVolHetFrame) self.inputVolHetFrame.layout().addWidget(self.inputVolHet) # select individual nodes self.inputSelectorVolHet = slicer.qMRMLNodeComboBox( self.inputVolHetFrame) self.inputSelectorVolHet.nodeTypes = (("vtkMRMLScalarVolumeNode"), "") self.inputSelectorVolHet.selectNodeUponCreation = False self.inputSelectorVolHet.addEnabled = False self.inputSelectorVolHet.removeEnabled = False self.inputSelectorVolHet.setMRMLScene(slicer.mrmlScene) self.inputVolHetFrame.layout().addWidget(self.inputSelectorVolHet) # add Data Node button self.addDataNodeButton = qt.QPushButton("Add Node", self.inputVolHetFrame) self.addDataNodeButton.objectName = 'AddDataNodeButton' self.addDataNodeButton.setToolTip("Add a Node to Queue") self.addDataNodeButton.connect('clicked()', self.onAddDataNodeButtonClicked) self.inputVolHetFrame.layout().addWidget(self.addDataNodeButton) ## data nodes Frame self.dataNodesFrame = ctk.ctkCollapsibleGroupBox( self.inputHeterogeneityCADCollapsibleButton) self.dataNodesFrame.title = "Nodes List" self.dataNodesFrame.collapsed = False self.dataNodesFrame.setLayout(qt.QVBoxLayout()) # all buttons frame self.allButtonsFrame = qt.QFrame( self.inputHeterogeneityCADCollapsibleButton) self.allButtonsFrame.objectName = 'AllButtonsFrameButton' self.allButtonsFrame.setLayout(qt.QVBoxLayout()) self.inputHeterogeneityCADLayout.addRow(self.dataNodesFrame, self.allButtonsFrame) # Data Nodes view # Use list view here with scroll area widget. self.dataScrollArea = qt.QScrollArea() self.dataNodesListWidget = qt.QListWidget() self.dataNodesListWidget.name = 'dataNodesListWidget' self.dataScrollArea.setWidget(self.dataNodesListWidget) self.dataNodesListWidget.resize(350, 100) self.dataNodesFrame.layout().addWidget(self.dataScrollArea) #self.listWidget.setProperty('SH_ItemView_ActivateItemOnSingleClick', 1) #self.listWidget.connect('activated(QModelIndex)', self.onActivated) # add all Data Nodes from scene button self.addAllDataNodesButton = qt.QPushButton("Add All Nodes From Scene", self.allButtonsFrame) self.addAllDataNodesButton.objectName = 'AddAllDataNodesButton' self.addAllDataNodesButton.setToolTip( "Add all Nodes from the Scene to Queue") self.addAllDataNodesButton.connect('clicked()', self.onAddAllDataNodesButtonClicked) self.allButtonsFrame.layout().addWidget(self.addAllDataNodesButton) # remove single Data Node self.removeDataNodeButton = qt.QPushButton("Remove Node", self.allButtonsFrame) self.removeDataNodeButton.objectName = 'RemoveDataNodeButton' self.removeDataNodeButton.setToolTip( "Removes Selected Node from the Queue.") self.removeDataNodeButton.connect('clicked()', self.onRemoveDataNodeButtonClicked) self.allButtonsFrame.layout().addWidget(self.removeDataNodeButton) # remove all Data Nodes button self.removeAllDataNodesButton = qt.QPushButton("Remove All Nodes", self.allButtonsFrame) self.removeAllDataNodesButton.objectName = 'RemoveAllDataNodesButton' self.removeAllDataNodesButton.setToolTip( "Removes All Nodes from the Queue.") self.removeAllDataNodesButton.connect( 'clicked()', self.onRemoveAllDataNodesButtonClicked) self.allButtonsFrame.layout().addWidget(self.removeAllDataNodesButton) # Use Label Map as ROI(segmentation output or user-selected ROI) self.inputLabelROIFrame = qt.QFrame( self.inputHeterogeneityCADCollapsibleButton) self.inputLabelROIFrame.setLayout(qt.QHBoxLayout()) self.inputHeterogeneityCADLayout.addRow(self.inputLabelROIFrame) # Enable Input Label Map as ROI self.inputLabelROI = qt.QLabel("Label Map ROI: ", self.inputLabelROIFrame) self.inputLabelROIFrame.layout().addWidget(self.inputLabelROI) # Select Input Label Map as ROI self.inputSelectorLabel = slicer.qMRMLNodeComboBox( self.inputLabelROIFrame) self.inputSelectorLabel.nodeTypes = (("vtkMRMLLabelMapVolumeNode"), "") self.inputSelectorLabel.selectNodeUponCreation = False self.inputSelectorLabel.renameEnabled = True self.inputSelectorLabel.removeEnabled = False self.inputSelectorLabel.noneEnabled = True self.inputSelectorLabel.addEnabled = False self.inputSelectorLabel.setMRMLScene(slicer.mrmlScene) self.inputLabelROIFrame.layout().addWidget(self.inputSelectorLabel) #End HeterogeneityCAD Inputs Collapsible Button ################################################# #HeterogeneityCAD Features Collapsible Button self.HeterogeneityCADCollapsibleButton = ctk.ctkCollapsibleButton() self.HeterogeneityCADCollapsibleButton.text = "HeterogeneityCAD Features Selection" self.layout.addWidget(self.HeterogeneityCADCollapsibleButton) self.featuresHeterogeneityCADLayout = qt.QFormLayout( self.HeterogeneityCADCollapsibleButton) # auto-generate QTabWidget Tabs and QCheckBoxes (subclassed in FeatureWidgetHelperLib) self.tabsFeatureClasses = FeatureWidgetHelperLib.CheckableTabWidget() self.featuresHeterogeneityCADLayout.addRow(self.tabsFeatureClasses) gridWidth, gridHeight = 3, 9 for featureClass in self.featureClassKeys: # by default, features from the following features classes are checked: if featureClass in [ "Node Information", "First-Order Statistics", "Morphology and Shape", "Texture: GLCM", "Texture: GLRL" ]: check = True else: check = False tabFeatureClass = qt.QWidget() tabFeatureClass.setLayout(qt.QGridLayout()) #featureList = (feature for feature in self.featureClassKeys[featureClass]) gridLayoutCoordinates = ((row, col) for col in range(gridWidth) for row in range(gridHeight)) for featureName in self.featureClassKeys[featureClass]: row, col = next(gridLayoutCoordinates, None) if featureName is None or row is None or col is None: break featureCheckboxWidget = FeatureWidgetHelperLib.FeatureWidget() featureCheckboxWidget.Setup(featureName=featureName, checkStatus=check) tabFeatureClass.layout().addWidget(featureCheckboxWidget, row, col) self.featureWidgets[featureClass].append(featureCheckboxWidget) self.tabsFeatureClasses.addTab(tabFeatureClass, featureClass, self.featureWidgets[featureClass], checkStatus=check) self.tabsFeatureClasses.setCurrentIndex(1) # note: try using itertools list merging with lists of GLRL diagonal self.heterogeneityFeatureWidgets = list( itertools.chain.from_iterable(self.featureWidgets.values())) self.classes = list(self.featureWidgets.keys()) # or reduce(lambda x,y: x+y, self.featureWidgets.values()) ########## Parameter options # add parameters for top-level feature classes self.tabsFeatureClasses.addParameter("Geometrical Measures", "Extrusion Parameter 1") self.tabsFeatureClasses.addParameter("Texture: GLCM", "GLCM Matrix Parameter 1") self.tabsFeatureClasses.addParameter("Texture: GLRL", "GLRL Matrix Parameter 1") # compile dict of feature classes with parameter names and values self.featureClassParametersDict = collections.OrderedDict() for featureClassWidget in self.tabsFeatureClasses.getFeatureClassWidgets( ): featureClassName = featureClassWidget.getName() self.featureClassParametersDict[ featureClassName] = collections.OrderedDict() self.updateFeatureClassParameterDict(0, featureClassWidget) for parameterName in featureClassWidget.widgetMenu.parameters: featureClassWidget.getParameterEditWindow( parameterName).connect( 'intValueChanged(int)', lambda intValue, featureClassWidget=featureClassWidget: self.updateFeatureClassParameterDict( intValue, featureClassWidget)) # add parameters for individual features for featureWidget in self.heterogeneityFeatureWidgets: if featureWidget.getName() == "Voxel Count": featureWidget.addParameter("Example Parameter 1") featureWidget.addParameter("Example Parameter 2") if featureWidget.getName() == "Gray Levels": featureWidget.addParameter("Example Parameter 1-GL") featureWidget.addParameter("Example Parameter 2-GL") # compile dict of features with parameter names and values self.featureParametersDict = collections.OrderedDict() for featureWidget in self.heterogeneityFeatureWidgets: featureName = featureWidget.getName() self.featureParametersDict[featureName] = collections.OrderedDict() self.updateFeatureParameterDict(0, featureWidget) for parameterName in featureWidget.widgetMenu.parameters: featureWidget.getParameterEditWindow(parameterName).connect( 'intValueChanged(int)', lambda intValue, featureWidget=featureWidget: self. updateFeatureParameterDict(intValue, featureWidget) ) #connect intvaluechanged signals to updateParamaterDict function ########## # Feature Buttons Frame and Layout self.featureButtonFrame = qt.QFrame( self.HeterogeneityCADCollapsibleButton) self.featureButtonFrame.setLayout(qt.QHBoxLayout()) self.featuresHeterogeneityCADLayout.addRow(self.featureButtonFrame) # HeterogeneityCAD Apply Button self.HeterogeneityCADButton = qt.QPushButton("Apply HeterogeneityCAD", self.featureButtonFrame) self.HeterogeneityCADButton.toolTip = "Analyze input volume using selected Heterogeneity Features." self.featureButtonFrame.layout().addWidget(self.HeterogeneityCADButton) self.HeterogeneityCADButton.connect( 'clicked()', self.onHeterogeneityCADButtonClicked) # Save Button self.saveButton = qt.QPushButton("Save to File", self.featureButtonFrame) self.saveButton.toolTip = "Save analyses to CSV file" self.saveButton.enabled = False self.featureButtonFrame.layout().addWidget(self.saveButton) self.saveButton.connect('clicked()', self.onSave) #End HeterogeneityCAD Features Collapsible Button ################################################# #Feature Summary Chart #Complete chart options, export list of user-selected options identified via connections to labelstatistics module self.chartOptions = ("Count", "Volume mm^3", "Volume cc", "Min", "Max", "Mean", "StdDev") self.StatisticsChartCollapsibleButton = ctk.ctkCollapsibleButton() self.StatisticsChartCollapsibleButton.text = "HeterogeneityCAD Features Summary" self.layout.addWidget(self.StatisticsChartCollapsibleButton) self.StatisticsChartLayout = qt.QFormLayout( self.StatisticsChartCollapsibleButton) self.StatisticsChartCollapsibleButton.collapsed = False #Table View to display Label statistics self.view = qt.QTableView(self.StatisticsChartCollapsibleButton) self.view.sortingEnabled = True self.StatisticsChartLayout.addWidget(self.view) self.view.minimumHeight = 175
def setup(self): #--------------------------------------------------------- # Batch Covert DICOM to NRRD self.BatchConvertCollapsibleButton = ctk.ctkCollapsibleButton() self.BatchConvertCollapsibleButton.text = "Batch convert DICOM to NRRD or NIFTI" self.layout.addWidget(self.BatchConvertCollapsibleButton) self.BatchConvertCollapsibleButton.collapsed = False self.BatchConvertFormLayout = qt.QFormLayout( self.BatchConvertCollapsibleButton) # Input 1: Input Directory selector self.input1Selector = qt.QLabel("Input Directory (DICOM): ", self.BatchConvertCollapsibleButton) self.input1Button = qt.QPushButton( "Select Main Input Directory of DICOM files") self.input1Button.toolTip = "Select main directory with DICOM files (folder names are patient names)" self.input1Button.enabled = True self.BatchConvertFormLayout.addRow(self.input1Selector, self.input1Button) # Input 2: Output Directory selector self.input2Selector = qt.QLabel("Output Directory: ", self.BatchConvertCollapsibleButton) self.input2Button = qt.QPushButton("Select Main Output Directory") self.input2Button.toolTip = "Select main directory for output NRRD or NIFTI files (folder names are patient names)" self.input2Button.enabled = True self.BatchConvertFormLayout.addRow(self.input2Selector, self.input2Button) # RTStruct Conversion self.contourConvertLabel = qt.QLabel( "Convert DICOM-RT Contours: ", self.BatchConvertCollapsibleButton) self.contourConvertSelectFrame = qt.QFrame( self.BatchConvertCollapsibleButton) self.contourConvertSelectFrame.setLayout(qt.QHBoxLayout()) self.contourConvertGroup = qt.QButtonGroup( self.contourConvertSelectFrame) self.noConvertButton = qt.QRadioButton("None") self.noConvertButton.checked = True self.allConvertButton = qt.QRadioButton("All") self.selectConvertButton = qt.QRadioButton("Select") self.contourConvertGroup.addButton(self.noConvertButton) self.contourConvertGroup.addButton(self.allConvertButton) self.contourConvertGroup.addButton(self.selectConvertButton) self.contourConvertSelectFrame.layout().addWidget(self.noConvertButton) self.contourConvertSelectFrame.layout().addWidget( self.allConvertButton) self.contourConvertSelectFrame.layout().addWidget( self.selectConvertButton) self.BatchConvertFormLayout.layout().addRow( self.contourConvertLabel, self.contourConvertSelectFrame) self.contourConvertCollapsibleButton = ctk.ctkCollapsibleButton( self.BatchConvertCollapsibleButton) self.contourConvertCollapsibleButton.text = "Select Contours to Convert" self.BatchConvertFormLayout.addRow( self.contourConvertCollapsibleButton) self.contourConvertCollapsibleButton.enabled = False self.contourConvertCollapsibleButton.collapsed = True self.contourConvertFormLayout = qt.QFormLayout( self.contourConvertCollapsibleButton) # Keywords to catch RTStruct Structures self.contoursFrame = qt.QFrame(self.contourConvertCollapsibleButton) self.contoursFrame.setLayout(qt.QVBoxLayout()) self.contoursFrame.setFrameStyle(2) self.contourConvertFormLayout.addWidget(self.contoursFrame) self.addContourButton = qt.QPushButton( "Add Contour to convert from RTStruct (separate keywords by comma)", self.contoursFrame) self.keywordsScrollWidget = qt.QWidget() self.keywordsScrollWidget.setLayout(qt.QFormLayout()) self.keywordsScroll = qt.QScrollArea() self.keywordsScroll.setWidgetResizable(True) self.keywordsScroll.setWidget(self.keywordsScrollWidget) self.contoursFrame.layout().addWidget(self.keywordsScroll) self.contoursFrame.layout().addWidget(self.addContourButton) # Settings Collapsible Button self.settingsCollapsibleButton = ctk.ctkCollapsibleButton() self.settingsCollapsibleButton.text = "Settings" self.settingsCollapsibleButton.setLayout(qt.QFormLayout()) self.layout.addWidget(self.settingsCollapsibleButton) # NRRD or NIFTI Radio Buttons self.fileFormatLabel = qt.QLabel("Output File Format: ", self.settingsCollapsibleButton) self.fileFormatSelectFrame = qt.QFrame(self.settingsCollapsibleButton) self.fileFormatSelectFrame.setLayout(qt.QFormLayout()) self.fileFormatGroup = qt.QButtonGroup(self.fileFormatSelectFrame) 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.fileFormatSelectFrame.layout().addRow(self.nrrdButton, self.niftiButton) self.settingsCollapsibleButton.layout().addRow( self.fileFormatLabel, self.fileFormatSelectFrame) # Use input DICOM Patient Directory names as PatientID or infer from DICOM Metadata self.patientIDLabel = qt.QLabel("Infer Patient IDs from: ", self.settingsCollapsibleButton) self.patientIDLabel.toolTip = "Use input DICOM Patient Directory names as PatientID or infer from DICOM Metadata" self.patientIDSelectFrame = qt.QFrame(self.settingsCollapsibleButton) self.patientIDSelectFrame.setLayout(qt.QFormLayout()) self.patientIDGroup = qt.QButtonGroup(self.patientIDSelectFrame) self.metadataButton = qt.QRadioButton("Series DICOM Metadata") self.metadataButton.checked = True self.inputDirButton = qt.QRadioButton("Input Patient Subdirectories") self.patientIDGroup.addButton(self.metadataButton) self.patientIDGroup.addButton(self.inputDirButton) self.patientIDSelectFrame.layout().addRow(self.metadataButton, self.inputDirButton) self.settingsCollapsibleButton.layout().addRow( self.patientIDLabel, self.patientIDSelectFrame) # Center Images option self.centerImagesLabel = qt.QLabel("Center Images: ", self.settingsCollapsibleButton) self.centerImagesSelectFrame = qt.QFrame( self.settingsCollapsibleButton) self.centerImagesSelectFrame.setLayout(qt.QFormLayout()) self.centerImagesGroup = qt.QButtonGroup(self.centerImagesSelectFrame) self.centerImagesButton = qt.QRadioButton("Yes") self.noCenterImagesButton = qt.QRadioButton("No") self.noCenterImagesButton.checked = True self.centerImagesGroup.addButton(self.centerImagesButton) self.centerImagesGroup.addButton(self.noCenterImagesButton) self.centerImagesSelectFrame.layout().addRow(self.centerImagesButton, self.noCenterImagesButton) self.settingsCollapsibleButton.layout().addRow( self.centerImagesLabel, self.centerImagesSelectFrame) # Center Labels option self.centerLabelsLabel = qt.QLabel("Center Labels: ", self.settingsCollapsibleButton) self.centerLabelsSelectFrame = qt.QFrame( self.settingsCollapsibleButton) self.centerLabelsSelectFrame.setLayout(qt.QFormLayout()) self.centerLabelsGroup = qt.QButtonGroup(self.centerLabelsSelectFrame) self.centerLabelsButton = qt.QRadioButton("Yes") self.noCenterLabelsButton = qt.QRadioButton("No") self.noCenterLabelsButton.checked = True self.centerLabelsGroup.addButton(self.centerLabelsButton) self.centerLabelsGroup.addButton(self.noCenterLabelsButton) self.centerLabelsSelectFrame.layout().addRow(self.centerLabelsButton, self.noCenterLabelsButton) self.settingsCollapsibleButton.layout().addRow( self.centerLabelsLabel, self.centerLabelsSelectFrame) # Parse and Save DICOM Metadata to CSV self.metadataExtractLabel = qt.QLabel("DICOM Metadata Extraction", self.settingsCollapsibleButton) self.metadataExtractLabel.toolTip = "Extract and Save all DICOM Metadata to a CSV file" self.metadataExtractSelectFrame = qt.QFrame( self.settingsCollapsibleButton) self.metadataExtractSelectFrame.setLayout(qt.QFormLayout()) self.metadataExtractGroup = qt.QButtonGroup( self.metadataExtractSelectFrame) self.extractCSVButton = qt.QRadioButton("CSV") self.extractCSVButton.checked = True #self.extractJSONButton = qt.QRadioButton("JSON") self.doNotExtractButton = qt.QRadioButton("None") self.metadataExtractGroup.addButton(self.extractCSVButton) self.metadataExtractGroup.addButton(self.doNotExtractButton) self.metadataExtractSelectFrame.layout().addRow( self.extractCSVButton, self.doNotExtractButton) self.settingsCollapsibleButton.layout().addRow( self.metadataExtractLabel, self.metadataExtractSelectFrame) # Apply Batch Convert button self.applyBatchButton = qt.QPushButton("Apply Batch Convert") self.applyBatchButton.toolTip = "Batch convert DICOM to NRRD or NIFTI files" self.layout.addWidget(self.applyBatchButton) self.applyBatchButton.enabled = False #--------------------------------------------------------- # Connections self.input1Button.connect('clicked(bool)', self.onInput1Button) self.input2Button.connect('clicked(bool)', self.onInput2Button) self.selectConvertButton.toggled.connect(self.selectConvert) self.addContourButton.connect('clicked(bool)', self.addContourFilterWidget) self.applyBatchButton.connect('clicked(bool)', self.onBatchApply)