def onExit(self, goingTo, transitionType): if goingTo.id() != 'Landmarks' and goingTo.id( ) != 'LoadData': # Change to next step return pNode = self.parameterNode() # TODO: add storeWidgetStateToParameterNode() -- move all pNode-related stuff # there? if self.__roi != None: self.__roi.RemoveObserver(self.__roiObserverTag) self.__roi.SetDisplayVisibility(0) if self.__roiSelector.currentNode() != None: pNode.SetNodeReferenceID('roiNode', self.__roiSelector.currentNode().GetID()) if self.__vrDisplayNode != None: #self.__vrDisplayNode.VisibilityOff() pNode.SetNodeReferenceID('vrDisplayNode', self.__vrDisplayNode.GetID()) if goingTo.id() == 'Landmarks': # Change to next step #create progress bar dialog self.progress = qt.QProgressDialog(slicer.util.mainWindow()) self.progress.minimumDuration = 0 self.progress.show() self.progress.setValue(0) self.progress.setMaximum(0) self.progress.setCancelButton(0) self.progress.setMinimumWidth(500) self.progress.setWindowModality(2) self.progress.setLabelText('Cropping and resampling volume...') slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.repaint() self.doStepProcessing() #close progress bar self.progress.setValue(2) self.progress.repaint() slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.close() self.progress = None super(DefineROIStep, self).onExit(goingTo, transitionType)
def onOk(self): address = self.dicomEntries['Destination Address'].text port = self.dicomEntries['Destination Port'].text settings = qt.QSettings() settings.setValue('DICOM.sendAddress', address) settings.setValue('DICOM.sendPort', port) self.progress = qt.QProgressDialog(slicer.util.mainWindow()) self.progress.minimumDuration = 0 self.progress.setMaximum(len(self.files)) self.progressValue = 0 try: DICOMLib.DICOMSender(self.files, address, port, progressCallback = self.onProgress) except Exception as result: qt.QMessageBox.warning(self.dialog, 'DICOM Send', 'Could not send data: %s' % result) self.progress.close() self.dialog.close()
def loadCheckedLoadables(self): """Invoke the load method on each plugin for the DICOMLoadable instances that are selected""" if self.advancedViewButton.checkState() == 0: self.examineForLoading() self.loadableTable.updateSelectedFromCheckstate() loadableCount = 0 for plugin in self.loadablesByPlugin: for loadable in self.loadablesByPlugin[plugin]: if loadable.selected: loadableCount += 1 self.progress = qt.QProgressDialog(self.window) self.progress.minimumDuration = 0 self.progress.show() self.progress.setValue(0) self.progress.setMaximum(loadableCount) step = 0 loadingResult = '' for plugin in self.loadablesByPlugin: for loadable in self.loadablesByPlugin[plugin]: if self.progress.wasCanceled: break slicer.app.processEvents() self.progress.setValue(step) slicer.app.processEvents() if loadable.selected: self.progress.labelText = '\nLoading %s' % loadable.name slicer.app.processEvents() if not plugin.load(loadable): loadingResult = '%s\nCould not load: %s as a %s' % ( loadingResult, loadable.name, plugin.loadType) step += 1 self.progress.setValue(step) slicer.app.processEvents() self.progress.close() self.progress = None if loadingResult: qt.QMessageBox.warning(slicer.util.mainWindow(), 'DICOM loading', loadingResult) if not self.setBrowserPersistence: self.close()
def onLoadButton(self): self.progress = qt.QProgressDialog(slicer.util.mainWindow()) self.progress.minimumDuration = 0 self.progress.show() self.progress.setValue(0) self.progress.setMaximum(100) uid = self.selection.data(self.dicomModelUIDRole) role = self.dicomModelTypes[self.selection.data( self.dicomModelTypeRole)] toLoad = {} if role == "Patient": self.progress.show() self.loadPatient(uid) elif role == "Study": self.progress.show() self.loadStudy(uid) elif role == "Series": self.loadSeries(uid) elif role == "Image": pass self.progress.close() self.progress = None
def loadCheckedLoadables(self): """Invoke the load method on each plugin for the DICOMLoadable instances that are selected""" self.loadableTable.updateCheckstate() loadableCount = 0 for plugin in self.loadablesByPlugin: for loadable in self.loadablesByPlugin[plugin]: if loadable.selected: loadableCount += 1 self.progress = qt.QProgressDialog(self.window) self.progress.minimumDuration = 0 self.progress.show() self.progress.setValue(0) self.progress.setMaximum(loadableCount) step = 0 for plugin in self.loadablesByPlugin: for loadable in self.loadablesByPlugin[plugin]: if self.progress.wasCanceled: break slicer.app.processEvents() self.progress.setValue(step) slicer.app.processEvents() if loadable.selected: self.progress.labelText = '\nLoading %s' % loadable.name slicer.app.processEvents() if not plugin.load(loadable): qt.QMessageBox.warning( slicer.util.mainWindow(), 'Load', 'Could not load: %s as a %s' % (loadable.name, plugin.loadType)) step += 1 self.progress.setValue(step) slicer.app.processEvents() self.progress.close() self.progress = None self.close()
def onEntry(self, comingFrom, transitionType): super(DefineROIStep, self).onEntry(comingFrom, transitionType) # setup the interface lm = slicer.app.layoutManager() lm.setLayout(3) #create progress bar dialog self.progress = qt.QProgressDialog(slicer.util.mainWindow()) self.progress.minimumDuration = 0 self.progress.show() self.progress.setValue(0) self.progress.setMaximum(0) self.progress.setCancelButton(0) self.progress.setMinimumWidth(500) self.progress.setWindowModality(2) self.progress.setLabelText('Generating Volume Rendering...') slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.repaint() #read scalar volume node ID from previous step pNode = self.parameterNode() self.__baselineVolume = pNode.GetNodeReference('baselineVolume') #if ROI was created previously, get its transformation matrix and update current ROI roiTransformNode = pNode.GetNodeReference('roiTransform') if not roiTransformNode: roiTransformNode = slicer.vtkMRMLLinearTransformNode() slicer.mrmlScene.AddNode(roiTransformNode) pNode.SetNodeReferenceID('roiTransform', roiTransformNode.GetID()) dm = vtk.vtkMatrix4x4() self.__baselineVolume.GetIJKToRASDirectionMatrix(dm) dm.SetElement(0, 3, 0) dm.SetElement(1, 3, 0) dm.SetElement(2, 3, 0) dm.SetElement(0, 0, abs(dm.GetElement(0, 0))) dm.SetElement(1, 1, abs(dm.GetElement(1, 1))) dm.SetElement(2, 2, abs(dm.GetElement(2, 2))) roiTransformNode.SetMatrixTransformToParent(dm) Helper.SetBgFgVolumes(self.__baselineVolume.GetID()) Helper.SetLabelVolume(None) # use this transform node to align ROI with the axes of the baseline # volume self.__roiTransformNode = pNode.GetNodeReference('roiTransform') if not self.__roiTransformNode: Helper.Error( 'Internal error! Error code CT-S2-NRT, please report!') # get the roiNode from parameters node, if it exists, and initialize the # GUI self.updateWidgetFromParameterNode(pNode) # start VR if self.__roi != None: self.__roi.SetDisplayVisibility(1) # Make sure the GUI is fully initilized because user will see it for a few seconds, while VR is being set up slicer.app.processEvents() self.InitVRDisplayNode() #close progress bar self.progress.setValue(2) self.progress.repaint() slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.close() self.progress = None #pNode.SetParameter('currentStep', self.stepid) qt.QTimer.singleShot(0, self.killButton)
def onEntry(self,comingFrom,transitionType): super(ApproachStep, self).onEntry(comingFrom, transitionType) # setup the interface lm = slicer.app.layoutManager() if lm == None: return #lm.setLayout(slicer.vtkMRMLLayoutNode.SlicerLayoutSideBySideView) customLayout = ("<layout type=\"horizontal\" split=\"true\" >" " <item>" " <view class=\"vtkMRMLSliceNode\" singletontag=\"Red\">" " <property name=\"orientation\" action=\"default\">Axial</property>" " <property name=\"viewlabel\" action=\"default\">R</property>" " <property name=\"viewcolor\" action=\"default\">#F34A33</property>" " </view>" " </item>" " <item>" " <view class=\"vtkMRMLSliceNode\" singletontag=\"Yellow\">" " <property name=\"orientation\" action=\"default\">Axial</property>" " <property name=\"viewlabel\" action=\"default\">Y</property>" " <property name=\"viewcolor\" action=\"default\">#EDD54C</property>" " </view>" " </item>" " <item>" " <view class=\"vtkMRMLSliceNode\" singletontag=\"Green\">" " <property name=\"orientation\" action=\"default\">Axial</property>" " <property name=\"viewlabel\" action=\"default\">G</property>" " <property name=\"viewcolor\" action=\"default\">#6EB04B</property>" " </view>" " </item>" "</layout>") customLayoutId=502 #layoutManager = slicer.app.layoutManager() lm.layoutLogic().GetLayoutNode().AddLayoutDescription(customLayoutId, customLayout) lm.setLayout(customLayoutId) markup = slicer.modules.markups.logic() markup.AddNewFiducialNode('Vertebrae Labels') landmarks = slicer.mrmlScene.GetNodesByName('Vertebrae Labels') self.fidNode = landmarks.GetItemAsObject(0) slicer.app.applicationLogic().PropagateVolumeSelection(1) #create progress bar dialog self.progress = qt.QProgressDialog(slicer.util.mainWindow()) self.progress.minimumDuration = 0 self.progress.show() self.progress.setValue(0) self.progress.setMaximum(0) self.progress.setCancelButton(0) self.progress.setMinimumWidth(500) self.progress.setWindowModality(2) self.progress.setLabelText('Generating Volume Rendering...') slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.repaint() #read scalar volume node ID from previous step pNode = self.__parameterNode baselineVolume = Helper.getNodeByID(pNode.GetParameter('baselineVolumeID')) self.__baselineVolume = baselineVolume roiTransformID = pNode.GetParameter('roiTransformID') roiTransformNode = None if roiTransformID != '': roiTransformNode = Helper.getNodeByID(roiTransformID) else: roiTransformNode = slicer.vtkMRMLLinearTransformNode() slicer.mrmlScene.AddNode(roiTransformNode) pNode.SetParameter('roiTransformID', roiTransformNode.GetID()) dm = vtk.vtkMatrix4x4() baselineVolume.GetIJKToRASDirectionMatrix(dm) dm.SetElement(0,3,0) dm.SetElement(1,3,0) dm.SetElement(2,3,0) dm.SetElement(0,0,abs(dm.GetElement(0,0))) dm.SetElement(1,1,abs(dm.GetElement(1,1))) dm.SetElement(2,2,abs(dm.GetElement(2,2))) roiTransformNode.SetAndObserveMatrixTransformToParent(dm) Helper.SetBgFgVolumes(pNode.GetParameter('baselineVolumeID')) Helper.SetLabelVolume(None) # use this transform node to align ROI with the axes of the baseline # volume roiTfmNodeID = pNode.GetParameter('roiTransformID') if roiTfmNodeID != '': self.__roiTransformNode = Helper.getNodeByID(roiTfmNodeID) else: Helper.Error('Internal error! Error code CT-S2-NRT, please report!') # get the roiNode from parameters node, if it exists, and initialize the # GUI self.updateWidgetFromParameterNode(pNode) if self.__roi != None: self.__roi.SetDisplayVisibility(0) self.InitVRDisplayNode() #close progress bar self.progress.setValue(2) self.progress.repaint() slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.close() self.progress = None #turn off rendering to save memory slicer.mrmlScene.GetNodesByName('GPURayCastVolumeRendering').GetItemAsObject(0).SetVisibility(0) #pNode.SetParameter('currentStep', self.stepid) # Enable Slice Intersections viewNodes = slicer.mrmlScene.GetNodesByClass('vtkMRMLSliceCompositeNode') viewNodes.UnRegister(slicer.mrmlScene) viewNodes.InitTraversal() viewNode = viewNodes.GetNextItemAsObject() while viewNode: viewNode.SetSliceIntersectionVisibility(1) viewNode = viewNodes.GetNextItemAsObject() self.redTransform = vtk.vtkTransform() viewSlice = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeRed') self.redTransform.SetMatrix(viewSlice.GetSliceToRAS()) #print "Red Transform" #print self.redTransform self.yellowTransform = vtk.vtkTransform() viewSlice = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeYellow') self.yellowTransform.SetMatrix(viewSlice.GetSliceToRAS()) #print "Yellow Transform" #print self.yellowTransform self.greenTransform = vtk.vtkTransform() viewSlice = slicer.mrmlScene.GetNodeByID('vtkMRMLSliceNodeGreen') self.greenTransform.SetMatrix(viewSlice.GetSliceToRAS()) #print "Green Transform" #print self.greenTransform n = self.__baselineVolume for color in ['Red', 'Yellow', 'Green']: a = slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceNode().GetFieldOfView() slicer.app.layoutManager().sliceWidget(color).sliceLogic().GetSliceCompositeNode().SetBackgroundVolumeID(n.GetID()) lm.sliceWidget("Yellow").sliceController().fitSliceToBackground() lm.sliceWidget("Red").sliceController().fitSliceToBackground() lm.sliceWidget("Green").sliceController().fitSliceToBackground() qt.QTimer.singleShot(0, self.killButton) self.showThreshold() self.loadLandmarks()
def offerLoadables(self, uid, role): """Get all the loadable options at the currently selected level and present them in the loadable table""" fileLists = [] if role == "Series": fileLists.append(slicer.dicomDatabase.filesForSeries(uid)) if role == "Study": series = slicer.dicomDatabase.seriesForStudy(uid) for serie in series: fileLists.append(slicer.dicomDatabase.filesForSeries(serie)) if role == "Patient": studies = slicer.dicomDatabase.studiesForPatient(uid) for study in studies: series = slicer.dicomDatabase.seriesForStudy(study) for serie in series: fileList = slicer.dicomDatabase.filesForSeries(serie) fileLists.append(fileList) allFileCount = missingFileCount = 0 for fileList in fileLists: for filePath in fileList: allFileCount += 1 if not os.path.exists(filePath): missingFileCount += 1 if missingFileCount > 0: qt.QMessageBox.warning( self.window, "DICOM", "Warning: %d of %d files listed in the database for this %s cannot be found on disk." % (missingFileCount, allFileCount, role)) if missingFileCount == allFileCount: return self.progress = qt.QProgressDialog(self.window) self.progress.modal = True self.progress.minimumDuration = 0 self.progress.show() self.progress.setValue(0) self.progress.setMaximum(len(slicer.modules.dicomPlugins)) step = 0 loadEnabled = False self.loadablesByPlugin = {} for pluginClass in slicer.modules.dicomPlugins: if not self.pluginInstances.has_key(pluginClass): self.pluginInstances[ pluginClass] = slicer.modules.dicomPlugins[pluginClass]() plugin = self.pluginInstances[pluginClass] if self.progress.wasCanceled: break self.progress.labelText = '\nChecking %s' % pluginClass slicer.app.processEvents() self.progress.setValue(step) slicer.app.processEvents() try: self.loadablesByPlugin[plugin] = plugin.examine(fileLists) loadEnabled = loadEnabled or self.loadablesByPlugin[ plugin] != [] except Exception, e: import traceback traceback.print_exc() qt.QMessageBox.warning( self.window, "DICOM", "Warning: Plugin failed: %s\n\nSee python console for error message." % pluginClass) print("DICOM Plugin failed: %s", str(e)) step += 1
def setup(self): """Init the widget """ # ScriptedLoadableModuleWidget.setup(self) settings = qt.QSettings() if (SlicerUtil.IsDevelopment): # reload button self.reloadButton = qt.QPushButton("Reload") self.reloadButton.toolTip = "Reload this module." self.reloadButton.name = "Reload" self.layout.addWidget(self.reloadButton) self.reloadButton.connect('clicked()', self.onBtnReloadClicked) self.logic = PicasaSnapLogic() self.__addObservers__() ######## Credentials self.credentialsCollapsibleButton = ctk.ctkCollapsibleButton() self.credentialsCollapsibleButton.text = "Credentials" self.layout.addWidget(self.credentialsCollapsibleButton) self.credentialsLayout = qt.QFormLayout( self.credentialsCollapsibleButton) self.isUserLogged = False self.loginLineEdit = qt.QLineEdit() self.credentialsLayout.addRow("Login: "******"Password: "******"Remember my credentials") self.rememberCredentialsCheckBox.toolTip = "Check for an automatic login when the application starts" self.loginButton = qt.QPushButton("Login") self.loginButton.toolTip = "Login in Picassa service (Google credentials)" self.logoutButton = qt.QPushButton("Logout") self.logoutButton.toolTip = "Logout to connect with another user's credentials" # Add all the items, they will be shown/hidden in refreshCredentialsUI function self.credentialsLayout.addRow(self.rememberCredentialsCheckBox, self.loginButton) self.credentialsLayout.addRow(None, self.logoutButton) ######## Snapshots (main frame) self.mainCollapsibleButton = ctk.ctkCollapsibleButton() self.mainCollapsibleButton.text = "Snapshots" self.layout.addWidget(self.mainCollapsibleButton) self.mainLayout = qt.QVBoxLayout(self.mainCollapsibleButton) ############### Current snapshots self.currentSnapshotsFrame = qt.QFrame() self.currentSnapshotsLayout = qt.QVBoxLayout() self.currentSnapshotsFrame.setLayout(self.currentSnapshotsLayout) self.currentSnapshotsFrame.setFrameShape(qt.QFrame.StyledPanel) self.mainLayout.addWidget(self.currentSnapshotsFrame) self.snapshotsLabel = qt.QLabel("Snapshots to upload:") self.snapshotsLabel.setStyleSheet( "font-weight:bold; font-size:14px; margin-bottom:10px") self.currentSnapshotsLayout.addWidget(self.snapshotsLabel) # Subframe that contains the checkbox list self.currentSnapshotsInnerFrame = qt.QFrame() self.currentSnapshotsInnerLayout = qt.QVBoxLayout() self.currentSnapshotsInnerFrame.setLayout( self.currentSnapshotsInnerLayout) self.currentSnapshotsLayout.addWidget(self.currentSnapshotsInnerFrame) self.noItemsLabel = qt.QLabel( "(There are not any snapshots at the moment)") # Add the label by default. It will be hidden if there is any snapshot self.currentSnapshotsInnerLayout.addWidget(self.noItemsLabel) self.loadExistingSnapshotsFirstLoad() ############### Albums # Try to login before getting the albums self.login() msgBox = None if self.isUserLogged: # Show message box while loading the data msgBox = qt.QMessageBox(qt.QMessageBox.Information, 'Login', 'Connecting with Picasa. Please wait...', qt.QMessageBox.Cancel) msgBox.show() try: self.albumNameFrame = qt.QFrame() self.albumNameLayout = qt.QHBoxLayout() self.albumNameFrame.setLayout(self.albumNameLayout) self.albumNameFrame.setFrameShape(qt.QFrame.StyledPanel) self.albumNameLabel = qt.QLabel("Album name:") self.albumNameLabel.setStyleSheet("font-weight:bold;") self.albumNamesComboBox = qt.QComboBox() self.loadAlbums() self.albumNameLayout.addWidget(self.albumNameLabel) self.albumNameLayout.addWidget(self.albumNamesComboBox) self.mainLayout.addWidget(self.albumNameFrame) ############### Tags self.tagsFrame = qt.QFrame() self.tagsLayout = qt.QGridLayout() self.tagsFrame.setLayout(self.tagsLayout) self.tagsFrame.setFrameShape(qt.QFrame.StyledPanel) self.tagsLabel = qt.QLabel( "Tags (select all that apply, you can filter o create new tags):" ) self.tagsLabel.setStyleSheet( "font-weight: bold; margin-bottom: 10px; margin-top: 5px") self.tagsLayout.addWidget(self.tagsLabel, 0, 0, 1, 3) # Add input to filter tags and button to add a new one self.tagsFilterLineEdit = qt.QLineEdit() self.tagsFilterLineEdit.toolTip = "Type here to filter your tags. If you press the return key all the visible tags will be checked" #self.tagsFilterLineEdit.setStyleSheet(style) self.tagsLayout.addWidget(self.tagsFilterLineEdit, 1, 0, 1, 2) self.newTagButton = qt.QPushButton("New tag") #self.newTagButton.setStyleSheet("background-color: #5D74C6; color:white") self.newTagButton.setIconSize(qt.QSize(20, 20)) self.newTagButton.setIcon( qt.QIcon(self.CIP_ICON_DIR + "/Plus - 48.png")) self.newTagButton.setFixedWidth(75) self.newTagButton.toolTip = "Add a new tag (the tag will not be created until you upload any picture with it)" self.tagsLayout.addWidget(self.newTagButton, 1, 2) self.loadTags() ############### Upload snapshots controls self.uploadSnapsButtonFrame = qt.QFrame() self.uploadSnapsLayout = qt.QHBoxLayout() self.uploadSnapsButtonFrame.setLayout(self.uploadSnapsLayout) #self(qt.QFrame.HLine) self.mainLayout.addWidget(self.uploadSnapsButtonFrame) self.uploadSnapshotsButton = qt.QPushButton() self.uploadSnapshotsButton.text = "Upload to Picasa!" self.uploadSnapshotsButton.toolTip = "Upload selected screenshots to Picassa" self.uploadSnapshotsButton.setStyleSheet( "background-color: #5D74C6; color: white; font-weight: bold; font-size:14px" ) self.uploadSnapshotsButton.setIcon( qt.QIcon(self.CIP_ICON_DIR + "/Upload - 64.png")) self.uploadSnapshotsButton.setIconSize(qt.QSize(24, 24)) self.uploadSnapshotsButton.setFixedSize(170, 35) self.uploadSnapsLayout.addWidget(self.uploadSnapshotsButton) ############### Progress bar self.progressBar = qt.QProgressDialog() self.progressBar.setMinimum(0) self.progressBar.setMinimumDuration(0) self.progressBar.setWindowModality(True) # Check for updates in CIP #autoUpdate = SlicerUtil.settingGetOrSetDefault("PicasaSnap", "AutoUpdate", 1) #uw = AutoUpdateWidget(parent=self.parent, autoUpdate=autoUpdate) #uw.addAutoUpdateCheckObserver(self.onAutoUpdateStateChanged) # self.uploadProgressFrame = qt.QFrame() # self.uploadProgressLayout = qt.QVBoxLayout() # self.uploadProgressFrame.setLayout(self.uploadProgressLayout) # # # Gif image # self.imUploading = qt.QMovie("%s/loading.gif" % self.CIP_ICON_DIR, qt.QByteArray()) # # Label to contain the gif # self.lblImLoading = qt.QLabel() # # Fix the dimensions of the image (by fixing the dimensions of the label that contains it) # self.lblImLoading.setFixedWidth(40) # # Other image parameters # self.imUploading.setCacheMode(qt.QMovie.CacheAll) # self.imUploading.setSpeed(100) # # Assign the label to the image (don't start it yet, it will be started when we are uploading) # self.lblImLoading.setMovie(self.imUploading) # #self.imUploading.start() # self.uploadProgressLayout.addWidget(self.lblImLoading) # # # Label that will show the progress # self.lblUploading = qt.QLabel("Uploading %i/%i images...") # self.uploadProgressLayout.addWidget(self.lblUploading) # # Cancel uploading button # self.btnCancelUpload = qt.QPushButton("Cancel") # self.btnCancelUpload.toolTip = "Cancel the process" # self.btnCancelUpload.setFixedWidth(100) # self.uploadProgressLayout.addWidget(self.btnCancelUpload) # self.mainLayout.addWidget(self.uploadProgressFrame) # # # Hide the progress frame # self.uploadProgressFrame.hide() ######## Connections self.uploadSnapshotsButton.connect( 'clicked (bool)', self.onUploadSnapshotsButtonClicked) self.loginButton.connect('clicked (bool)', self.onLoginButtonClicked) self.logoutButton.connect('clicked (bool)', self.onLogoutButtonClicked) self.loginLineEdit.returnPressed.connect( self.onLoginPasswordReturnKeyPressed) self.passwordLineEdit.returnPressed.connect( self.onLoginPasswordReturnKeyPressed) self.albumNamesComboBox.connect("currentIndexChanged (int)", self.onAlbumsCurrentIndexChanged) self.newTagButton.connect('clicked (bool)', self.onNewTagButtonClicked) self.tagsFilterLineEdit.connect('textEdited (QString)', self.onFilterTagsEdited) self.tagsFilterLineEdit.returnPressed.connect( self.onFilterTagsReturnKeyPressed) # Add vertical spacer self.layout.addStretch(1) finally: # Hide MesageBox if it was visible if msgBox: msgBox.close()
def doStepProcessing(self): print 'Step processing' ''' timer = qt.QTimer() timer.setInterval(1000) timer.setSingleShot(0) timer.connect('timeout()', self.updateProgress) ''' # pop up progress dialog to prevent user from messing around self.progress = qt.QProgressDialog(slicer.util.mainWindow()) self.progress.minimumDuration = 0 self.progress.show() self.progress.setValue(0) self.progress.setMaximum(0) self.progress.setCancelButton(0) self.progress.setWindowModality(2) self.progress.setLabelText('Registering followup image to baseline') slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.repaint() # qt.QTimer.singleShot(0, self.updateProgress) ''' Step logic: 1) register followup to baseline 2) resample followup to baseline ROI 3) given baselineROI, followupROI and baseline segmentation, run each of the change detection metrics ''' pNode = self.parameterNode() # (1) register followup to baseline # If the followup transform is initialized, do not register! if pNode.GetParameter('followupTransformID') == '': baselineVolumeID = pNode.GetParameter('baselineVolumeID') followupVolumeID = pNode.GetParameter('followupVolumeID') self.__followupTransform = slicer.vtkMRMLLinearTransformNode() slicer.mrmlScene.AddNode(self.__followupTransform) parameters = {} parameters["fixedVolume"] = baselineVolumeID parameters["movingVolume"] = followupVolumeID parameters["initializeTransformMode"] = "useMomentsAlign" parameters["useRigid"] = True parameters["useScaleVersor3D"] = False parameters["useScaleSkewVersor3D"] = False parameters["useAffine"] = True parameters["linearTransform"] = self.__followupTransform.GetID() # apparently this is needed even if not b-spline (see bug report 1542) parameters["forceMINumberOfThreads"] = -1 # FIXME: make sure brainsfit is available first? cliNode = None cliNode = slicer.cli.run(slicer.modules.brainsfit, cliNode, parameters, wait_for_completion = True) status = cliNode.GetStatusString() ''' while status != 'Completed': # while status == 'Running' or status == 'Scheduled' or status == 'Idle': slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.repaint() status = cliNode.GetStatusString() print 'Registration completed: status = ', status ''' if status == 'Completed': Helper.Info('registration completed OK') else: Helper.ErrorPopup('Registration step failed. Unable to proceed. Please quit Slicer and report this issue including the output from the error log.') return pNode.SetParameter('followupTransformID', self.__followupTransform.GetID()) print 'AnalyzeROIStep: registration completed!' else: print 'AnalyzeROIStep: registration not required!' self.progress.setLabelText('Estimating changes') slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.repaint() # self.__cliObserverTag = self.__cliNode.AddObserver('ModifiedEvent', self.processRegistrationCompletion) # self.__registrationStatus.setText('Wait ...') # self.__registrationButton.setEnabled(0) # (2) resample followup to baselineROI baselineVolumeROI = slicer.mrmlScene.GetNodeByID(pNode.GetParameter('croppedBaselineVolumeID')) followupVolume = slicer.mrmlScene.GetNodeByID(pNode.GetParameter('followupVolumeID')) followupVolumeROI = slicer.modules.volumes.logic().CloneVolume(slicer.mrmlScene, followupVolume, 'followupROI') parameters = {} parameters["inputVolume"] = pNode.GetParameter('followupVolumeID') parameters["referenceVolume"] = pNode.GetParameter('croppedBaselineVolumeID') parameters["outputVolume"] = followupVolumeROI.GetID() parameters["transformationFile"] = pNode.GetParameter('followupTransformID') parameters["interpolationType"] = "bs" cliNode = None cliNode = slicer.cli.run(slicer.modules.resamplescalarvectordwivolume, cliNode, parameters, 1) status = cliNode.GetStatusString() if status == 'Completed': Helper.Info('ResampleScalarVectorDWIVolume completed OK') pNode.SetParameter('croppedFollowupVolumeID', followupVolumeROI.GetID()) else: Helper.Error('Failed to resample!') # (3) calculate each of the metrics # most of the parameters will be the same for all metrics parameters = {} parameters['baselineVolume'] = pNode.GetParameter('croppedBaselineVolumeID') parameters['followupVolume'] = pNode.GetParameter('croppedFollowupVolumeID') parameters['baselineSegmentationVolume'] = pNode.GetParameter('croppedBaselineVolumeSegmentationID') baselineVolume = slicer.mrmlScene.GetNodeByID(pNode.GetParameter('croppedBaselineVolumeID')) metricsList = pNode.GetParameter('metrics') if metricsList == '': Helper.Error('doStepProcessing(): metrics list is empty!') resultVolumesList = '' moduleManager = slicer.app.moduleManager() for m in string.split(metricsList,','): # TODO: processing should be separated from the workflow! need to move # this into a different place pluginName = m # pluginName = pluginName.lower() vl = slicer.modules.volumes.logic() outputVolume = vl.CreateLabelVolume(slicer.mrmlScene, baselineVolume, 'changesVolume_'+m) outputReport = slicer.app.temporaryPath+os.sep+pluginName+'_report.txt' parameters["tmpDirectory"] = slicer.app.temporaryPath parameters['outputVolume'] = outputVolume.GetID() parameters['reportFileName'] = outputReport plugin = moduleManager.module(pluginName) if plugin != None: cliNode = None Helper.Info('About to run '+m+' metric!') cliNode = slicer.cli.run(plugin, cliNode, parameters, 1) ''' TODO: error checking for CLI! ''' labelsColorNode = slicer.modules.colors.logic().GetColorTableNodeID(10) outputVolume.GetDisplayNode().SetAndObserveColorNodeID(labelsColorNode) if resultVolumesList != '': resultVolumesList = resultVolumesList + ',' resultVolumesList = resultVolumesList + outputVolume.GetID() outputVolume.SetDescription(Helper.readFileAsString(outputReport)) pNode.SetParameter('resultVolumes', resultVolumesList) Helper.Info('Selected metrics: '+pNode.GetParameter('metrics')) Helper.Info('Metrics processing results:'+pNode.GetParameter('resultVolumes')) # close the progress window ''' timer.stop() ''' self.progress.setValue(2) self.progress.repaint() slicer.app.processEvents(qt.QEventLoop.ExcludeUserInputEvents) self.progress.close() self.progress = None
def __init__(self, dataNode, labelNode, featureParameterDict, featureClassParametersDict, keys): self.dataNode = dataNode self.labelNode = labelNode self.featureParameterDict = featureParameterDict # ( keys=featureNames,values=dict(keys=parameterNames,values=parameterValues) ) self.featureClassParametersDict = featureClassParametersDict # ( keys=featureClassNames,values=dict(keys=parameterNames,values=parameterValues) ) self.keys = keys # initialize Progress Bar self.progressBar = qt.QProgressDialog(slicer.util.mainWindow()) self.progressBar.minimumDuration = 0 self.progressBar.show() self.progressBar.setValue(0) self.progressBar.setMaximum(len(self.keys)) self.progressBar.labelText = 'Calculating for %s: ' % self.dataNode.GetName( ) # create Numpy Arrays self.nodeArrayVolume = self.createNumpyArray(self.dataNode) self.nodeArrayLabelMapROI = self.createNumpyArray(self.labelNode) # extract voxel coordinates (ijk) and values from self.dataNode within the ROI defined by self.labelNode self.targetVoxels, self.targetVoxelsCoordinates = self.tumorVoxelsAndCoordinates( self.nodeArrayLabelMapROI, self.nodeArrayVolume) # create a padded, rectangular matrix with shape equal to the shape of the tumor self.matrix, self.matrixCoordinates = self.paddedTumorMatrixAndCoordinates( self.targetVoxels, self.targetVoxelsCoordinates) # get Histogram data self.bins, self.grayLevels, self.numGrayLevels = self.getHistogramData( self.targetVoxels) ######## # Manage feature classes for Heterogeneity feature calculations and consolidate into self.FeatureVector # TODO: create a parent class for all feature classes self.FeatureVector = collections.OrderedDict() # Node Information self.updateProgressBar(self.progressBar, self.dataNode.GetName(), "Node Information", len(self.FeatureVector)) self.nodeInformation = FeatureExtractionLib.NodeInformation( self.dataNode, self.labelNode, self.keys) self.FeatureVector.update(self.nodeInformation.EvaluateFeatures()) # First Order Statistics self.updateProgressBar(self.progressBar, self.dataNode.GetName(), "First Order Statistics", len(self.FeatureVector)) self.firstOrderStatistics = FeatureExtractionLib.FirstOrderStatistics( self.targetVoxels, self.bins, self.numGrayLevels, self.keys) self.FeatureVector.update(self.firstOrderStatistics.EvaluateFeatures()) # Shape/Size and Morphological Features) self.updateProgressBar(self.progressBar, self.dataNode.GetName(), "Morphology Statistics", len(self.FeatureVector)) # extend padding by one row/column for all 6 directions maxDimsSA = tuple(map(operator.add, self.matrix.shape, ([2, 2, 2]))) matrixSA, matrixSACoordinates = self.padMatrix(self.matrix, self.matrixCoordinates, maxDimsSA, self.targetVoxels) self.morphologyStatistics = FeatureExtractionLib.MorphologyStatistics( self.labelNode, matrixSA, matrixSACoordinates, self.targetVoxels, self.keys) self.FeatureVector.update(self.morphologyStatistics.EvaluateFeatures()) # Texture Features(GLCM) self.updateProgressBar(self.progressBar, self.dataNode.GetName(), "GLCM Texture Features", len(self.FeatureVector)) self.textureFeaturesGLCM = FeatureExtractionLib.TextureGLCM( self.grayLevels, self.numGrayLevels, self.matrix, self.matrixCoordinates, self.targetVoxels, self.keys) self.FeatureVector.update(self.textureFeaturesGLCM.EvaluateFeatures()) # Texture Features(GLRL) self.updateProgressBar(self.progressBar, self.dataNode.GetName(), "GLRL Texture Features", len(self.FeatureVector)) self.textureFeaturesGLRL = FeatureExtractionLib.TextureGLRL( self.grayLevels, self.numGrayLevels, self.matrix, self.matrixCoordinates, self.targetVoxels, self.keys) self.FeatureVector.update(self.textureFeaturesGLRL.EvaluateFeatures()) # Geometrical Measures # TODO: progress bar does not update to Geometrical Measures while calculating (create separate thread?) self.updateProgressBar(self.progressBar, self.dataNode.GetName(), "Geometrical Measures", len(self.FeatureVector)) self.geometricalMeasures = FeatureExtractionLib.GeometricalMeasures( self.labelNode, self.matrix, self.matrixCoordinates, self.targetVoxels, self.keys) self.FeatureVector.update(self.geometricalMeasures.EvaluateFeatures()) # Renyi Dimensions self.updateProgressBar(self.progressBar, self.dataNode.GetName(), "Renyi Dimensions", len(self.FeatureVector)) # extend padding to dimension lengths equal to next power of 2 maxDims = tuple( [int(pow(2, math.ceil(numpy.log2(numpy.max(self.matrix.shape))))) ] * 3) matrixPadded, matrixPaddedCoordinates = self.padMatrix( self.matrix, self.matrixCoordinates, maxDims, self.targetVoxels) self.renyiDimensions = FeatureExtractionLib.RenyiDimensions( matrixPadded, matrixPaddedCoordinates, self.keys) self.FeatureVector.update(self.renyiDimensions.EvaluateFeatures()) # close progress bar self.updateProgressBar(self.progressBar, self.dataNode.GetName(), "Populating Summary Table", len(self.FeatureVector)) self.progressBar.close() self.progressBar = None # filter for user-queried features only self.FeatureVector = collections.OrderedDict( (k, self.FeatureVector[k]) for k in self.keys)