Пример #1
0
  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)
Пример #2
0
 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
Пример #3
0
 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
Пример #4
0
 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
Пример #5
0
 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
Пример #6
0
 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
Пример #7
0
    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)
Пример #8
0
  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
Пример #9
0
  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
Пример #10
0
  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
Пример #11
0
    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
Пример #12
0
  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()
Пример #13
0
    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)
Пример #14
0
  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)
Пример #15
0
    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()
Пример #16
0
    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()
Пример #17
0
  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()
Пример #18
0
  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)