def __init__(self, dicomBrowser=None, parent="mainWindow"): VTKObservationMixin.__init__(self) qt.QWidget.__init__(self, slicer.util.mainWindow() if parent == "mainWindow" else parent) self.pluginInstances = {} self.fileLists = [] self.extensionCheckPending = False self.settings = qt.QSettings() self.dicomBrowser = dicomBrowser if dicomBrowser is not None else slicer.app.createDICOMBrowserForMainDatabase() self.browserPersistent = settingsValue('DICOM/BrowserPersistent', False, converter=toBool) self.advancedView = settingsValue('DICOM/advancedView', 0, converter=int) self.horizontalTables = settingsValue('DICOM/horizontalTables', 0, converter=int) self.setup() self.dicomBrowser.connect('directoryImported()', self.onDirectoryImported) self.dicomBrowser.connect('sendRequested(QStringList)', self.onSend) # Load when double-clicked on an item in the browser self.dicomBrowser.dicomTableManager().connect('patientsDoubleClicked(QModelIndex)', self.patientStudySeriesDoubleClicked) self.dicomBrowser.dicomTableManager().connect('studiesDoubleClicked(QModelIndex)', self.patientStudySeriesDoubleClicked) self.dicomBrowser.dicomTableManager().connect('seriesDoubleClicked(QModelIndex)', self.patientStudySeriesDoubleClicked)
def timerCallback(): # Prompting for extension may be undesirable in custom applications. # DICOM/PromptForExtensions key can be used to disable this feature. promptForExtensionsEnabled = settingsValue('DICOM/PromptForExtensions', True, converter=toBool) if promptForExtensionsEnabled: self.promptForExtensions() self.extensionCheckPending = False
def getSavedDICOMDetailsWidgetType(default="window"): widgetType = settingsValue('DICOM/BrowserWidgetType', default) widgetClass = DICOMWidget.getDetailsWidgetClassForType(widgetType) if not widgetClass: qt.QSettings().setValue('DICOM/BrowserWidgetType', widgetType) widgetClass = DICOMWidget.getDetailsWidgetClassForType(default) return widgetClass
def onSettingsButton(self, status): for groupName in self.settingsWidgetNames.keys(): visible = settingsValue('DICOM/%s.visible' % groupName, True, converter=toBool) for name in self.settingsWidgetNames[groupName]: control = self._findChildren(name) control.visible = False if visible: control.visible = self.settingsButton.checked
def override(self): try: parent = slicer.util.findChildren(text='Data Probe')[0] except IndexError: print("No Data Probe frame - cannot create DataProbe") return SlicerAstroDataProbeLogic(parent) # disable 3DSlicer Annotations sliceAnnotations = slicer.modules.DataProbeInstance.infoWidget.sliceAnnotations sliceAnnotations.sliceViewAnnotationsEnabled = 0 sliceAnnotations.updateSliceViewFromGUI() sliceAnnotations.updateEnabledButtons() sliceAnnotations.sliceViewAnnotationsCheckBox.checked = 0 settingsValue('DataProbe/sliceViewAnnotations.enabled', 0, converter=int)
def export(self): # Perform export success = self.createDICOMFileForScene() # Get flag from application settings whether exported data needs to be imported importExportedData = settingsValue('DICOM/ImportExportedDataset', False, converter=toBool) if success and importExportedData: self.addFilesToDatabase() return success
def __init__(self,dicomBrowser=None): VTKObservationMixin.__init__(self) self.dicomBrowser = dicomBrowser # initialize the dicomDatabase # - pick a default and let the user know if not slicer.dicomDatabase: self.promptForDatabaseDirectory() if self.dicomBrowser is None: # This creates a DICOM database in the current working directory if nothing else # is specified in the settings, therefore promptForDatabaseDirectory must be called before this. self.dicomBrowser = ctk.ctkDICOMBrowser() self.browserPersistent = settingsValue('DICOM/BrowserPersistent', False, converter=toBool) self.tableDensity = settingsValue('DICOM/tableDensity', 'Compact') self.popupGeometry = settingsValue('DICOM/detailsPopup.geometry', qt.QRect()) self.advancedView = settingsValue('DICOM/advancedView', 0, converter=int) self.horizontalTables = settingsValue('DICOM/horizontalTables', 0, converter=int) self.volumeNameTemplate = settingsValue('DICOM/volumeNameTemplate', "") self.create() self.popupPositioned = False self.pluginInstances = {} self.fileLists = [] setDatabasePrecacheTags(self.dicomBrowser) self.dicomBrowser.connect('databaseDirectoryChanged(QString)', self.onDatabaseDirectoryChanged) # Update visibility for name in [ 'ActionImport', 'ActionExport', 'ActionQuery', 'ActionSend', 'ActionRemove', 'ActionRepair', 'ActionViewMetadata', 'AdvancedViewCheckBox', 'HorizontalViewCheckBox', 'BrowserPersistentCheckBox' ]: visible = settingsValue('DICOM/%s.visible' % name, True, converter=toBool) control = self._findChildren(name) control.visible = visible # Define set of widgets that should be hidden/shown together self.settingsWidgetNames = { 'DatabaseButton' : ('DatabaseNameLabel', 'DirectoryButton'), 'TableDensityComboBox' : ('tablesDensityLabel', 'tableDensityComboBox') } # Hide the settings button if all associated widgets should be hidden settingsButtonHidden = True for groupName in self.settingsWidgetNames.keys(): settingsButtonHidden = settingsButtonHidden and not settingsValue('DICOM/%s.visible' % groupName, True, converter=toBool) self.settingsButton.visible = not settingsButtonHidden
def __init__(self,dicomBrowser=None): VTKObservationMixin.__init__(self) self.dicomBrowser = dicomBrowser # initialize the dicomDatabase # - pick a default and let the user know if not slicer.dicomDatabase: self.promptForDatabaseDirectory() if self.dicomBrowser == None: # This creates a DICOM database in the current working directory if nothing else # is specified in the settings, therefore promptForDatabaseDirectory must be called before this. self.dicomBrowser = ctk.ctkDICOMBrowser() self.browserPersistent = settingsValue('DICOM/BrowserPersistent', False, converter=toBool) self.tableDensity = settingsValue('DICOM/tableDensity', 'Compact') self.popupGeometry = settingsValue('DICOM/detailsPopup.geometry', qt.QRect()) self.advancedView = settingsValue('DICOM/advancedView', 0, converter=int) self.horizontalTables = settingsValue('DICOM/horizontalTables', 0, converter=int) self.create() self.popupPositioned = False self.pluginInstances = {} self.fileLists = [] setDatabasePrecacheTags(self.dicomBrowser) self.dicomBrowser.connect('databaseDirectoryChanged(QString)', self.onDatabaseDirectoryChanged) # Update visibility for name in [ 'ActionImport', 'ActionExport', 'ActionQuery', 'ActionSend', 'ActionRemove', 'ActionRepair', 'ActionViewMetadata', 'AdvancedViewCheckBox', 'HorizontalViewCheckBox', 'BrowserPersistentCheckBox' ]: visible = settingsValue('DICOM/%s.visible' % name, True, converter=toBool) control = self._findChildren(name) control.visible = visible # Define set of widgets that should be hidden/shown together self.settingsWidgetNames = { 'DatabaseButton' : ('DatabaseNameLabel', 'DirectoryButton'), 'TableDensityComboBox' : ('tablesDensityLabel', 'tableDensityComboBox') } # Hide the settings button if all associated widgets should be hidden settingsButtonHidden = True for groupName in self.settingsWidgetNames.keys(): settingsButtonHidden = settingsButtonHidden and not settingsValue('DICOM/%s.visible' % groupName, True, converter=toBool) self.settingsButton.visible = not settingsButtonHidden
def examine(self, fileLists): """ Returns a list of DICOMLoadable instances corresponding to ways of interpreting the fileLists parameter. Top-level examine() calls various individual strategies implemented in examineFiles*(). """ self.detailedLogging = settingsValue('DICOM/detailedLogging', False, converter=toBool) timer = vtk.vtkTimerLog() timer.StartTimer() loadables = [] allfiles = [] for files in fileLists: loadables += self.examineFiles(files) # this strategy sorts the files into groups loadables += self.examineFilesIPPAcqTime(files) allfiles += files # here all files are lumped into one list for the situations when # individual frames should be parsed from series loadables += self.examineFilesMultiseries(allfiles) if len(allfiles) > len(files): # only examineFilesIPPAcqTime again if there are multiple file groups loadables += self.examineFilesIPPAcqTime(allfiles) # this strategy sorts the files into groups loadables += self.examineFilesIPPInstanceNumber(allfiles) # If Sequences module is available then duplicate all the loadables # for loading them as volume sequence. # A slightly higher confidence value is set for volume sequence loadables, # therefore by default data will be loaded as volume sequence. if hasattr(slicer.modules, 'sequences'): seqLoadables = [] for loadable in loadables: seqLoadable = DICOMLib.DICOMLoadable() seqLoadable.files = loadable.files seqLoadable.tooltip = loadable.tooltip.replace( ' frames MultiVolume by ', ' frames Volume Sequence by ') seqLoadable.name = loadable.name.replace( ' frames MultiVolume by ', ' frames Volume Sequence by ') seqLoadable.multivolume = loadable.multivolume seqLoadable.selected = loadable.selected seqLoadable.confidence = loadable.confidence seqLoadable.loadAsVolumeSequence = True seqLoadables.append(seqLoadable) # Among all selected loadables, the ones that are listed first will be selected by default, # therefore we need to prepend loadables if sequence format is preferred. # Determine from settings loading into sequence node should have higher confidence (selected by default). settings = qt.QSettings() sequenceFormatPreferred = (settings.value( "DICOM/PreferredMultiVolumeImportFormat", "default") == "sequence") if sequenceFormatPreferred: # prepend loadables[0:0] = seqLoadables else: # append loadables += seqLoadables timer.StopTimer() if self.detailedLogging: logging.debug( f"MultiVolumeImporterPlugin: found {len(loadables)} loadables in {len(allfiles)} files in {timer.GetElapsedTime():.1f}sec." ) return loadables
def __init__(self, layoutManager=None): VTKObservationMixin.__init__(self) self.hasVTKPVScalarBarActor = hasattr(slicer, 'vtkPVScalarBarActor') if not self.hasVTKPVScalarBarActor: slicer.logging.warning("SliceAnnotations: Disable features relying on vtkPVScalarBarActor") self.layoutManager = layoutManager if self.layoutManager is None: self.layoutManager = slicer.app.layoutManager() self.layoutManager.connect("destroyed()", self.onLayoutManagerDestroyed) self.dataProbeUtil = DataProbeUtil.DataProbeUtil() self.dicomVolumeNode = 0 self.sliceViewNames = [] self.popupGeometry = qt.QRect() self.cornerTexts =[] # Bottom Left Corner Text self.cornerTexts.append({ '1-Label':{'text':'','category':'A'}, '2-Foreground':{'text':'','category':'A'}, '3-Background':{'text':'','category':'A'} }) # Bottom Right Corner Text # Not used - orientation figure may be drawn there self.cornerTexts.append({ '1-TR':{'text':'','category':'A'}, '2-TE':{'text':'','category':'A'} }) # Top Left Corner Text self.cornerTexts.append({ '1-PatientName':{'text':'','category':'B'}, '2-PatientID':{'text':'','category':'A'}, '3-PatientInfo':{'text':'','category':'B'}, '4-Bg-SeriesDate':{'text':'','category':'B'}, '5-Fg-SeriesDate':{'text':'','category':'B'}, '6-Bg-SeriesTime':{'text':'','category':'C'}, '7-Bg-SeriesTime':{'text':'','category':'C'}, '8-Bg-SeriesDescription':{'text':'','category':'C'}, '9-Fg-SeriesDescription':{'text':'','category':'C'} }) # Top Right Corner Text self.cornerTexts.append({ '1-Institution-Name':{'text':'','category':'B'}, '2-Referring-Phisycian':{'text':'','category':'B'}, '3-Manufacturer':{'text':'','category':'C'}, '4-Model':{'text':'','category':'C'}, '5-Patient-Position':{'text':'','category':'A'}, '6-TR':{'text':'','category':'A'}, '7-TE':{'text':'','category':'A'} }) self.annotationsDisplayAmount = 0 # self.scene = slicer.mrmlScene self.sliceViews = {} # If there are no user settings load defaults self.sliceViewAnnotationsEnabled = settingsValue('DataProbe/sliceViewAnnotations.enabled', 1, converter=int) self.bottomLeft = settingsValue('DataProbe/sliceViewAnnotations.bottomLeft', 1, converter=int) self.topLeft = settingsValue('DataProbe/sliceViewAnnotations.topLeft', 0, converter=int) self.topRight = settingsValue('DataProbe/sliceViewAnnotations.topRight', 0, converter=int) self.fontFamily = settingsValue('DataProbe/sliceViewAnnotations.fontFamily', 'Times') self.fontSize = settingsValue('DataProbe/sliceViewAnnotations.fontSize', 14, converter=int) self.backgroundDICOMAnnotationsPersistence = settingsValue( 'DataProbe/sliceViewAnnotations.bgDICOMAnnotationsPersistence', 0, converter=int) self.scalarBarEnabled = settingsValue('DataProbe/sliceViewAnnotations.scalarBarEnabled', 0, converter=int) self.scalarBarEnabledLastStatus = self.scalarBarEnabled self.scalarBarSelectedLayer = 'background' self.rangeLabelFormat = settingsValue('DataProbe/sliceViewAnnotations.rangeLabelFormat', '%G') self.parameter = 'sliceViewAnnotationsEnabled' self.parameterNode = self.dataProbeUtil.getParameterNode() self.addObserver(self.parameterNode, vtk.vtkCommand.ModifiedEvent, self.updateGUIFromMRML) self.maximumTextLength= 35 self.create() if self.sliceViewAnnotationsEnabled: self.updateSliceViewFromGUI()
def setup(self): ScriptedLoadableModuleWidget.setup(self) # This module is often used in developer mode, therefore # collapse reload & test section by default. if hasattr(self, "reloadCollapsibleButton"): self.reloadCollapsibleButton.collapsed = True self.dragAndDropEventFilter = DICOMLoadingByDragAndDropEventFilter() globals()['d'] = self self.testingServer = None self.browserWidget = None self.directoryButton = None # Load widget from .ui file (created by Qt Designer) uiWidget = slicer.util.loadUI(self.resourcePath('UI/DICOM.ui')) self.layout.addWidget(uiWidget) self.ui = slicer.util.childWidgetVariables(uiWidget) self.browserWidget = DICOMLib.SlicerDICOMBrowser() self.browserWidget.objectName = 'SlicerDICOMBrowser' slicer.modules.DICOMInstance.setBrowserWidgetInDICOMLayout( self.browserWidget) layoutManager = slicer.app.layoutManager() if layoutManager is not None: layoutManager.layoutChanged.connect(self.onLayoutChanged) viewArrangement = slicer.app.layoutManager().layoutLogic( ).GetLayoutNode().GetViewArrangement() self.ui.showBrowserButton.checked = ( viewArrangement == slicer.vtkMRMLLayoutNode.SlicerLayoutDicomBrowserView) # connect to the 'Show DICOM Browser' button self.ui.showBrowserButton.connect('clicked()', self.toggleBrowserWidget) self.ui.importButton.connect('clicked()', self.browserWidget.dicomBrowser, 'openImportDialog()') self.ui.subjectHierarchyTree.setMRMLScene(slicer.mrmlScene) self.ui.subjectHierarchyTree.currentItemChanged.connect( self.onCurrentItemChanged) self.ui.subjectHierarchyTree.currentItemModified.connect( self.onCurrentItemModified) self.subjectHierarchyCurrentVisibility = False self.ui.subjectHierarchyTree.setColumnHidden( self.ui.subjectHierarchyTree.model().idColumn, True) # # DICOM networking # self.ui.networkingFrame.collapsed = True self.ui.queryServerButton.connect('clicked()', self.browserWidget.dicomBrowser, "openQueryDialog()") self.ui.toggleListener.connect('toggled(bool)', self.onToggleListener) settings = qt.QSettings() self.ui.runListenerAtStart.checked = settingsValue( 'DICOM/RunListenerAtStart', False, converter=toBool) self.ui.runListenerAtStart.connect('toggled(bool)', self.onRunListenerAtStart) # Testing server - not exposed (used for development) self.toggleServer = qt.QPushButton("Start Testing Server") self.ui.networkingFrame.layout().addWidget(self.toggleServer) self.toggleServer.connect('clicked()', self.onToggleServer) self.verboseServer = qt.QCheckBox("Verbose") self.ui.networkingFrame.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() # # Browser settings # self.ui.browserSettingsFrame.collapsed = True self.updateDatabaseDirectoryFromBrowser( self.browserWidget.dicomBrowser.databaseDirectory) # Synchronize database selection between browser and this widget self.ui.directoryButton.directoryChanged.connect( self.updateDatabaseDirectoryFromWidget) self.browserWidget.dicomBrowser.databaseDirectoryChanged.connect( self.updateDatabaseDirectoryFromBrowser) self.ui.browserAutoHideCheckBox.checked = not settingsValue( 'DICOM/BrowserPersistent', False, converter=toBool) self.ui.browserAutoHideCheckBox.stateChanged.connect( self.onBrowserAutoHideStateChanged) self.ui.repairDatabaseButton.connect('clicked()', self.browserWidget.dicomBrowser, "onRepairAction()") self.ui.clearDatabaseButton.connect('clicked()', self.onClearDatabase) # connect to the main window's dicom button mw = slicer.util.mainWindow() if mw: try: action = slicer.util.findChildren(mw, name='LoadDICOMAction')[0] action.connect('triggered()', self.onOpenBrowserWidget) except IndexError: logging.error( 'Could not connect to the main window DICOM button') self.databaseRefreshRequestTimer = qt.QTimer() self.databaseRefreshRequestTimer.setSingleShot(True) # If not receiving new file for 2 seconds then a database update is triggered. self.databaseRefreshRequestTimer.setInterval(2000) self.databaseRefreshRequestTimer.connect('timeout()', self.requestDatabaseRefresh)
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) self.runListenerAtStart.checked = settingsValue('DICOM/RunListenerAtStart', False, converter=toBool) 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) self.detailsPopup = self.getSavedDICOMDetailsWidgetType()() # XXX Slicer 4.5 - Remove these. Here only for backward compatibility. self.dicomBrowser = self.detailsPopup.dicomBrowser self.tables = self.detailsPopup.tables # connect to the 'Show DICOM Browser' button self.showBrowserButton = qt.QPushButton('Show DICOM Browser') self.dicomFrame.layout().addWidget(self.showBrowserButton) self.showBrowserButton.connect('clicked()', self.onOpenDetailsPopup) # connect to the main window's dicom button mw = slicer.util.mainWindow() if mw: try: action = slicer.util.findChildren(mw,name='LoadDICOMAction')[0] action.connect('triggered()',self.onOpenDetailsPopup) except IndexError: logging.error('Could not connect to the main window DICOM button') if hasattr(slicer, 'dicomListener'): slicer.dicomListener.fileToBeAddedCallback = self.onListenerToAddFile slicer.dicomListener.fileAddedCallback = self.onListenerAddedFile slicer.dicomDatabase.connect('databaseChanged()', self.onDatabaseChanged) # the recent activity frame self.activityFrame = ctk.ctkCollapsibleButton(self.parent) self.activityFrame.setLayout(qt.QVBoxLayout()) self.activityFrame.setText("Recent DICOM Activity") self.layout.addWidget(self.activityFrame) self.recentActivity = DICOMLib.DICOMRecentActivityWidget(self.activityFrame,detailsPopup=self.detailsPopup) self.activityFrame.layout().addWidget(self.recentActivity) self.requestUpdateRecentActivity() # Add spacer to layout self.layout.addStretch(1)
def __init__(self, layoutManager=None): VTKObservationMixin.__init__(self) self.layoutManager = layoutManager if self.layoutManager is None: self.layoutManager = slicer.app.layoutManager() self.layoutManager.connect("destroyed()", self.onLayoutManagerDestroyed) self.dataProbeUtil = DataProbeUtil.DataProbeUtil() self.dicomVolumeNode = 0 # Cache recently used extracted DICOM values. # Getting all necessary DICOM values from the database (tag cache) # would slow down slice browsing significantly. # We may have several different volumes shown in different slice views, # so we keep in the cache a number of items, not just 2. self.extractedDICOMValuesCacheSize = 12 import collections self.extractedDICOMValuesCache = collections.OrderedDict() self.sliceViewNames = [] self.popupGeometry = qt.QRect() self.cornerTexts = [] # Bottom Left Corner Text self.cornerTexts.append({ '1-Label': { 'text': '', 'category': 'A' }, '2-Foreground': { 'text': '', 'category': 'A' }, '3-Background': { 'text': '', 'category': 'A' } }) # Bottom Right Corner Text # Not used - orientation figure may be drawn there self.cornerTexts.append({ '1-TR': { 'text': '', 'category': 'A' }, '2-TE': { 'text': '', 'category': 'A' } }) # Top Left Corner Text self.cornerTexts.append({ '1-PatientName': { 'text': '', 'category': 'B' }, '2-PatientID': { 'text': '', 'category': 'A' }, '3-PatientInfo': { 'text': '', 'category': 'B' }, '4-Bg-SeriesDate': { 'text': '', 'category': 'B' }, '5-Fg-SeriesDate': { 'text': '', 'category': 'B' }, '6-Bg-SeriesTime': { 'text': '', 'category': 'C' }, '7-Bg-SeriesTime': { 'text': '', 'category': 'C' }, '8-Bg-SeriesDescription': { 'text': '', 'category': 'C' }, '9-Fg-SeriesDescription': { 'text': '', 'category': 'C' } }) # Top Right Corner Text self.cornerTexts.append({ '1-Institution-Name': { 'text': '', 'category': 'B' }, '2-Referring-Phisycian': { 'text': '', 'category': 'B' }, '3-Manufacturer': { 'text': '', 'category': 'C' }, '4-Model': { 'text': '', 'category': 'C' }, '5-Patient-Position': { 'text': '', 'category': 'A' }, '6-TR': { 'text': '', 'category': 'A' }, '7-TE': { 'text': '', 'category': 'A' } }) self.annotationsDisplayAmount = 0 # self.scene = slicer.mrmlScene self.sliceViews = {} # If there are no user settings load defaults self.sliceViewAnnotationsEnabled = settingsValue( 'DataProbe/sliceViewAnnotations.enabled', 1, converter=int) self.bottomLeft = settingsValue( 'DataProbe/sliceViewAnnotations.bottomLeft', 1, converter=int) self.topLeft = settingsValue('DataProbe/sliceViewAnnotations.topLeft', 0, converter=int) self.topRight = settingsValue( 'DataProbe/sliceViewAnnotations.topRight', 0, converter=int) self.fontFamily = settingsValue( 'DataProbe/sliceViewAnnotations.fontFamily', 'Times') self.fontSize = settingsValue( 'DataProbe/sliceViewAnnotations.fontSize', 14, converter=int) self.backgroundDICOMAnnotationsPersistence = settingsValue( 'DataProbe/sliceViewAnnotations.bgDICOMAnnotationsPersistence', 0, converter=int) self.sliceViewAnnotationsEnabledparameter = 'sliceViewAnnotationsEnabled' self.parameterNode = self.dataProbeUtil.getParameterNode() self.addObserver(self.parameterNode, vtk.vtkCommand.ModifiedEvent, self.updateGUIFromMRML) self.maximumTextLength = 35 self.create() if self.sliceViewAnnotationsEnabled: self.updateSliceViewFromGUI()
def setup(self): self.detailsPopup = None self.setDetailsPopup(self.getSavedDICOMDetailsWidgetType()()) # XXX Slicer 4.5 - Remove these. Here only for backward compatibility. self.dicomBrowser = self.detailsPopup.dicomBrowser self.tables = self.detailsPopup.tables layoutManager = slicer.app.layoutManager() if layoutManager is not None: layoutManager.layoutChanged.connect(self.onLayoutChanged) # connect to the 'Show DICOM Browser' button self.showBrowserButton = qt.QPushButton('Show DICOM database browser') self.showBrowserButton.setCheckable(True) self.layout.addWidget(self.showBrowserButton) self.showBrowserButton.setStyleSheet("font:Bold;" "font-size:12px") self.showBrowserButton.connect('clicked()', self.toggleDetailsPopup) self.loadedDataLabel = qt.QLabel("Loaded data") self.loadedDataLabel.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Fixed) self.layout.addWidget(self.loadedDataLabel) font = qt.QFont() font.setBold(True) font.setPointSize(12) self.loadedDataLabel.setFont(font) self.layout.addWidget(self.loadedDataLabel) self.subjectHierarchyTree = slicer.qMRMLSubjectHierarchyTreeView() self.layout.addWidget(self.subjectHierarchyTree) self.subjectHierarchyTree.setMRMLScene(slicer.mrmlScene) self.subjectHierarchyTree.currentItemChanged.connect( self.onCurrentItemChanged) self.subjectHierarchyTree.currentItemModified.connect( self.onCurrentItemModified) self.subjectHierarchyCurrentVisibility = False self.subjectHierarchyTree.setColumnHidden( self.subjectHierarchyTree.model().idColumn, True) self.browserSettingsWidget = ctk.ctkCollapsibleGroupBox() self.browserSettingsWidget.title = "Browser settings" self.layout.addWidget(self.browserSettingsWidget) self.browserSettingsWidget.collapsed = True self.browserSettingsWidget.setLayout(qt.QFormLayout()) self.directoryButton = ctk.ctkDirectoryButton() self.browserSettingsWidget.layout().addRow("Local database:", self.directoryButton) self.directoryButton.directoryChanged.connect( self.onDatabaseDirectoryButtonChanged) self.onDatabaseDirectoryDetailsPopupChanged( self.detailsPopup.dicomBrowser.databaseDirectory) self.tableDensityComboBox = qt.QComboBox() self.browserSettingsWidget.layout().addRow("Table density:", self.tableDensityComboBox) self.tableDensityComboBox.currentIndexChanged.connect( self.onTableDensityChanged) self.updateTableDensityComboBox() self.horizontalCheckBox = qt.QCheckBox() self.horizontalCheckBox.checked = settingsValue( 'DICOM/horizontalTables', 0, converter=int) self.horizontalCheckBox.stateChanged.connect( self.onHorizontalStateChanged) self.browserSettingsWidget.layout().addRow("Horizontal:", self.horizontalCheckBox) self.browserPersistentCheckBox = qt.QCheckBox() self.browserPersistentCheckBox.checked = settingsValue( 'DICOM/BrowserPersistent', False, converter=toBool) self.browserPersistentCheckBox.stateChanged.connect( self.onBrowserPersistentStateChanged) self.browserSettingsWidget.layout().addRow( "Browser persistent:", self.browserPersistentCheckBox) self.additionalSettingsLayout = qt.QHBoxLayout() # # servers # # testing server - not exposed (used for development) self.localFrame = ctk.ctkCollapsibleButton(self.parent) self.localFrame.setLayout(qt.QVBoxLayout()) self.localFrame.setText("Servers") self.layout.addWidget(self.localFrame) self.localFrame.collapsed = True self.toggleServer = qt.QPushButton("Start Testing Server") self.localFrame.layout().addWidget(self.toggleServer) self.toggleServer.connect('clicked()', self.onToggleServer) self.verboseServer = qt.QCheckBox("Verbose") self.localFrame.layout().addWidget(self.verboseServer) # advanced options - not exposed to end users # developers can uncomment these lines to access testing server self.toggleServer.hide() self.verboseServer.hide() # Listener settings = qt.QSettings() self.toggleListener = qt.QPushButton() self.toggleListener.checkable = True if hasattr(slicer, 'dicomListener'): self.toggleListener.text = "Stop Listener" slicer.dicomListener.process.connect( 'stateChanged(QProcess::ProcessState)', self.onListenerStateChanged) else: self.toggleListener.text = "Start Listener" self.localFrame.layout().addWidget(self.toggleListener) self.toggleListener.connect('clicked()', self.onToggleListener) self.runListenerAtStart = qt.QCheckBox( "Start Listener when Slicer Starts") self.localFrame.layout().addWidget(self.runListenerAtStart) self.runListenerAtStart.checked = settingsValue( 'DICOM/RunListenerAtStart', False, converter=toBool) self.runListenerAtStart.connect('clicked()', self.onRunListenerAtStart) # connect to the main window's dicom button mw = slicer.util.mainWindow() if mw: try: action = slicer.util.findChildren(mw, name='LoadDICOMAction')[0] action.connect('triggered()', self.onOpenDetailsPopup) except IndexError: logging.error( 'Could not connect to the main window DICOM button') if hasattr(slicer, 'dicomListener'): slicer.dicomListener.fileToBeAddedCallback = self.onListenerToAddFile slicer.dicomListener.fileAddedCallback = self.onListenerAddedFile slicer.dicomDatabase.connect('databaseChanged()', self.onDatabaseChanged) # the recent activity frame self.activityFrame = ctk.ctkCollapsibleButton(self.parent) self.activityFrame.collapsed = True self.activityFrame.setLayout(qt.QVBoxLayout()) self.activityFrame.setText("Recent DICOM Activity") self.layout.addWidget(self.activityFrame) self.recentActivity = DICOMLib.DICOMRecentActivityWidget( self.activityFrame, detailsPopup=self.detailsPopup) self.activityFrame.layout().addWidget(self.recentActivity) self.requestUpdateRecentActivity()
def __init__(self): self.hasVTKPVScalarBarActor = hasattr(slicer, 'vtkPVScalarBarActor') if not self.hasVTKPVScalarBarActor: slicer.logging.warning("SliceAnnotations: Disable features relying on vtkPVScalarBarActor") self.dataProbeUtil = DataProbeUtil.DataProbeUtil() self.dicomVolumeNode = 0 self.sliceViewNames = [] self.popupGeometry = qt.QRect() self.cornerTexts =[] # Bottom Left Corner Text self.cornerTexts.append({ '1-Label':{'text':'','category':'A'}, '2-Foreground':{'text':'','category':'A'}, '3-Background':{'text':'','category':'A'} }) # Bottom Right Corner Text # Not used - orientation figure will be draw there self.cornerTexts.append({ '1-TR':{'text':'','category':'A'}, '2-TE':{'text':'','category':'A'} }) # Top Left Corner Text self.cornerTexts.append({ '1-PatientName':{'text':'','category':'B'}, '2-PatientID':{'text':'','category':'A'}, '3-PatientInfo':{'text':'','category':'B'}, '4-Bg-SeriesDate':{'text':'','category':'B'}, '5-Fg-SeriesDate':{'text':'','category':'B'}, '6-Bg-SeriesTime':{'text':'','category':'C'}, '7-Bg-SeriesTime':{'text':'','category':'C'}, '8-Bg-SeriesDescription':{'text':'','category':'C'}, '9-Fg-SeriesDescription':{'text':'','category':'C'} }) # Top Rihgt Corner Text self.cornerTexts.append({ '1-Institution-Name':{'text':'','category':'B'}, '2-Referring-Phisycian':{'text':'','category':'B'}, '3-Manufacturer':{'text':'','category':'C'}, '4-Model':{'text':'','category':'C'}, '5-Patient-Position':{'text':'','category':'A'}, '6-TR':{'text':'','category':'A'}, '7-TE':{'text':'','category':'A'} }) self.layoutManager = slicer.app.layoutManager() self.sliceCornerAnnotations = {} self.annotationsDisplayAmount = 0 # If there is no user settings load defaults settings = qt.QSettings() self.topLeftAnnotationDisplay = settingsValue( 'DataProbe/sliceViewAnnotations.topLeft', 1, converter=int) self.topRightAnnotationDisplay = settingsValue( 'DataProbe/sliceViewAnnotations.topRight', 1, converter=int) self.bottomLeftAnnotationDisplay = settingsValue( 'DataProbe/sliceViewAnnotations.bottomLeft', 1, converter=int) self.showSliceViewAnnotations = settingsValue( 'DataProbe/sliceViewAnnotations.show', 1, converter=int) self.showScalingRuler = settingsValue( 'DataProbe/sliceViewAnnotations.showScalingRuler', 1, converter=int) self.showScalingRulerLastStatus = self.showScalingRuler self.showColorScalarBar = settingsValue( 'DataProbe/sliceViewAnnotations.showColorScalarBar', 0, converter=int) self.showColorScalarBarLastStatus = self.showColorScalarBar self.fontFamily = settingsValue( 'DataProbe/sliceViewAnnotations.fontFamily', 'Times') self.fontSize = settingsValue( 'DataProbe/sliceViewAnnotations.fontSize', 14, converter=int) self.maximumTextLength= 35 self.backgroundDicomAnnotationsPersistence = settingsValue( 'DataProbe/sliceViewAnnotations.bgDicomAnnotationsPersistence', 0, converter=int) self.rangeLabelFormat = settingsValue( 'DataProbe/sliceViewAnnotations.rangeLabelFormat', '%G') self.parameter = 'showSliceViewAnnotations' self.parameterNode = self.dataProbeUtil.getParameterNode() self.parameterNodeTag = self.parameterNode.AddObserver( vtk.vtkCommand.ModifiedEvent, self.updateGUIFromMRML) self.colorbarSelectedLayer = 'background' self.create() if self.showSliceViewAnnotations: self.updateSliceViewFromGUI()
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) self.runListenerAtStart.checked = settingsValue('DICOM/RunListenerAtStart', False, converter=toBool) 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) self.detailsPopup = DICOMLib.DICOMDetailsPopup() # XXX Slicer 4.5 - Remove these. Here only for backward compatibility. self.dicomBrowser = self.detailsPopup.dicomBrowser self.tables = self.detailsPopup.tables # connect to the 'Show DICOM Browser' button self.showBrowserButton = qt.QPushButton('Show DICOM Browser') self.dicomFrame.layout().addWidget(self.showBrowserButton) self.showBrowserButton.connect('clicked()', self.detailsPopup.open) # connect to the main window's dicom button mw = slicer.util.mainWindow() if mw: try: action = slicer.util.findChildren(mw,name='LoadDICOMAction')[0] action.connect('triggered()',self.detailsPopup.open) except IndexError: logging.error('Could not connect to the main window DICOM button') if hasattr(slicer, 'dicomListener'): slicer.dicomListener.fileToBeAddedCallback = self.onListenerToAddFile slicer.dicomListener.fileAddedCallback = self.onListenerAddedFile slicer.dicomDatabase.connect('databaseChanged()', self.onDatabaseChanged) # the recent activity frame self.activityFrame = ctk.ctkCollapsibleButton(self.parent) self.activityFrame.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)