def estimate(self): """Run parameter estimation function then emit :attr:`sigFitWidgetSignal` with a dictionary containing a status message and a list of fit parameters estimations in the format defined in :attr:`silx.math.fit.fitmanager.FitManager.fit_results` The emitted dictionary has an *"event"* key that can have following values: - *'EstimateStarted'* - *'EstimateFailed'* - *'EstimateFinished'* """ try: theory_name = self.fitmanager.selectedtheory estimation_function = self.fitmanager.theories[ theory_name].estimate if estimation_function is not None: ddict = {'event': 'EstimateStarted', 'data': None} self._emitSignal(ddict) self.fitmanager.estimate(callback=self.fitStatus) else: msg = qt.QMessageBox(self) msg.setIcon(qt.QMessageBox.Information) text = "Function does not define a way to estimate\n" text += "the initial parameters. Please, fill them\n" text += "yourself in the table and press Start Fit\n" msg.setText(text) msg.setWindowTitle('FitWidget Message') msg.exec() return except Exception as e: # noqa (we want to catch and report all errors) _logger.warning('Estimate error: %s', traceback.format_exc()) msg = qt.QMessageBox(self) msg.setIcon(qt.QMessageBox.Critical) msg.setWindowTitle("Estimate Error") msg.setText("Error on estimate: %s" % e) msg.exec() ddict = {'event': 'EstimateFailed', 'data': None} self._emitSignal(ddict) return self.guiParameters.fillFromFit(self.fitmanager.fit_results, view='Fit') self.guiParameters.removeAllViews(keep='Fit') ddict = { 'event': 'EstimateFinished', 'data': self.fitmanager.fit_results } self._emitSignal(ddict)
def displayExceptionBox(message, exc_info): """ Display an exception as a MessageBox :param str message: A context message :param Union[tuple,Exception] exc_info: An exception or the output of exc_info. """ logger.error(message, exc_info=True) if isinstance(exc_info, BaseException): exc_info = (type(exc_info), exc_info, exc_info.__traceback__) elif not isinstance(exc_info, tuple): exc_info = sys.exc_info() if exc_info[2] is not None: # Mimic the syntax of the default Python exception import traceback detailed = (''.join(traceback.format_tb(exc_info[2]))) detailed = '{1}\nTraceback (most recent call last):\n{2}{0}: {1}'.format( exc_info[0].__name__, exc_info[1], detailed) else: # There is no backtrace detailed = '{0}: {1}'.format(exc_info[0].__name__, exc_info[1]) from silx.gui import qt msg = qt.QMessageBox() msg.setWindowTitle(message) msg.setIcon(qt.QMessageBox.Critical) msg.setInformativeText("%s" % exc_info[1]) msg.setDetailedText(detailed) msg.raise_() msg.exec_()
def startFit(self): """Run fit, then emit :attr:`sigFitWidgetSignal` with a dictionary containing a status message and a list of fit parameters results in the format defined in :attr:`silx.math.fit.fitmanager.FitManager.fit_results` The emitted dictionary has an *"event"* key that can have following values: - *'FitStarted'* - *'FitFailed'* - *'FitFinished'* """ self.fitmanager.fit_results = self.guiParameters.getFitResults() try: ddict = {'event': 'FitStarted', 'data': None} self._emitSignal(ddict) self.fitmanager.runfit(callback=self.fitStatus) except Exception as e: # noqa (we want to catch and report all errors) _logger.warning('Estimate error: %s', traceback.format_exc()) msg = qt.QMessageBox(self) msg.setIcon(qt.QMessageBox.Critical) msg.setWindowTitle("Fit Error") msg.setText("Error on Fit: %s" % e) msg.exec() ddict = {'event': 'FitFailed', 'data': None} self._emitSignal(ddict) return self.guiParameters.fillFromFit(self.fitmanager.fit_results, view='Fit') self.guiParameters.removeAllViews(keep='Fit') ddict = {'event': 'FitFinished', 'data': self.fitmanager.fit_results} self._emitSignal(ddict) return
def setup(self): """Open a print dialog to ensure the :attr:`printer` is set. If the setting fails or is cancelled, :attr:`printer` is reset to *None*. """ if self.printer is None: self.printer = qt.QPrinter() if self.printDialog is None: self.printDialog = qt.QPrintDialog(self.printer, self) if self.printDialog.exec_(): if self.printer.width() <= 0 or self.printer.height() <= 0: self.message = qt.QMessageBox(self) self.message.setIcon(qt.QMessageBox.Critical) self.message.setText( "Unknown library error \non printer initialization") self.message.setWindowTitle("Library Error") self.message.setModal(0) self.printer = None return self.printer.setFullPage(True) self._updatePrinter() else: # printer setup cancelled, check for a possible previous configuration if self.page is None: # not initialized self.printer = None
def createCombined(self): if self.node is None: return ind = self.combineType.currentIndex() if ind == 0: return if ind == csp.COMBINE_PCA: msgBox = qt.QMessageBox() msgBox.information(self, 'Not implemented', 'PCA is not implemented yet', buttons=qt.QMessageBox.Close) return nPCA = self.combineN.value() # !!! TODO !!! # isStopHere = self.stopHereCB.checkState() == qt.Qt.Checked isStoppedAt = self.combineStopCB.checkState() == qt.Qt.Checked kw = dict(dataFormat={'combine': ind}, colorTag=ind) kw['originNode'] = self.node if isStoppedAt: for it in csi.selectedItems: it.terminalNode = csi.nodes[self.combineStop.currentText()] isMoveToGroup = self.combineMoveToGroupCB.checkState() == qt.Qt.Checked model = self.node.widget.tree.model() model.beginResetModel() csi.selectedItems[0].parentItem.insert_item(csi.selectedItems, csi.selectedItems[0].row(), **kw) model.endResetModel() model.dataChanged.emit(qt.QModelIndex(), qt.QModelIndex()) if isMoveToGroup: self.node.widget.tree.groupItems()
def __displayLicense(self): """Displays the license used by silx.""" text = self.getHtmlLicense() licenseDialog = qt.QMessageBox(self) licenseDialog.setWindowTitle("License") licenseDialog.setText(text) licenseDialog.exec_()
def _errorMessage(self, informativeText=''): """Display an error message.""" # TODO issue with QMessageBox size fixed and too small msg = qt.QMessageBox(self.plot) msg.setIcon(qt.QMessageBox.Critical) msg.setInformativeText(informativeText + ' ' + str(sys.exc_info()[1])) msg.setDetailedText(traceback.format_exc()) msg.exec_()
def __onAbort(self): abort_diag = Qt.QMessageBox(Qt.QMessageBox.Information, 'Aborting...', '<b>Cancelling merge.</b>' '<center>Please wait...</center>', parent=self) self.__abort_diag = abort_diag abort_diag.setTextFormat(Qt.Qt.RichText) abort_diag.setAttribute(Qt.Qt.WA_DeleteOnClose) abort_diag.setStandardButtons(Qt.QMessageBox.NoButton) abort_diag.show() self.__merger.abort(wait=False)
def load_project(self, fname): configProject = config.ConfigParser() configProject.optionxform = str # makes it case sensitive try: configProject.read(fname) except Exception: msg = qt.QMessageBox() msg.setIcon(qt.QMessageBox.Critical) msg.critical(self, "Cannot load project", "Invalid project file {0}".format(fname)) return self.restore_perspective(configProject) dataTree = config.get(configProject, 'Data', 'tree', []) os.chdir(os.path.dirname(fname)) csi.model.importData(dataTree, configData=configProject)
def __slotParseBnClicked(self): self.info_wid = None parseBn = self.__parseBn specFile = self.__input['specfile'] imgDir = self.__input['imgdir'] # version = self.__input['version'] padding = self.__input['padding'] offset = self.__input['offset'] spec_h5 = os.path.join(self.__tmp_dir_merge, 'temp_spec.h5') try: self.__parser = KmapSpecParser( specFile, spec_h5, img_dir=imgDir, # version=version, nr_offset=offset, nr_padding=padding, callback=self.__sigParsed.emit) except Exception as ex: msg = ('Parsing failed: {0}.\n' 'Message : {1}.' ''.format(ex.__class__.__name__, str(ex))) Qt.QMessageBox.critical(self, 'Parse error.', msg) return parseBn.setEnabled(False) parseBn.setText('Parsing...') info_wid = Qt.QMessageBox(Qt.QMessageBox.Information, 'Parsing...', '<b>Parsing SPEC file and matching image' ' files.</b>' '<center>Please wait...</center>', parent=self) info_wid.setTextFormat(Qt.Qt.RichText) info_wid.setAttribute(Qt.Qt.WA_DeleteOnClose) info_wid.setStandardButtons(Qt.QMessageBox.NoButton) info_wid.show() self.info_wid = info_wid self.__parser.parse(blocking=False)
def exception(parent, title, exc_info, logger=None): """ Display an exception as a MessageBox :param str title: A context message (displayed a s a title) :param qt.QWidget parent: The parent widget :param Union[tuple,Exception] exc_info: An exception or the output of exc_info. :param object logger: Logger to record the error inside. If `None` a default logger is provided. """ if logger is None: logger = _logger logger.error(title, exc_info=True) if isinstance(exc_info, BaseException): exc_info = (type(exc_info), exc_info, exc_info.__traceback__) elif not isinstance(exc_info, tuple): exc_info = sys.exc_info() if exc_info[2] is not None: # Mimic the syntax of the default Python exception import traceback detailed = (''.join(traceback.format_tb(exc_info[2]))) detailed = '{1}\nTraceback (most recent call last):\n{2}{0}: {1}'.format( exc_info[0].__name__, exc_info[1], detailed) else: # There is no backtrace detailed = '{0}: {1}'.format(exc_info[0].__name__, exc_info[1]) msg = qt.QMessageBox(parent=parent) msg.setWindowTitle(title) msg.setIcon(qt.QMessageBox.Critical) msg.setInformativeText("%s" % exc_info[1]) msg.setDetailedText(detailed) msg.raise_() msg.exec_()
def DoAction(self): if self.timer.isActive(): self.timer.stop() else: self.datDir = self.u.tB_Directory.toPlainText() self.trimRange = [self.u.sB_low.value(), self.u.sB_high.value()] if os.path.isdir(self.datDir) and self.u.tE_header.toPlainText(): self.u.progressBar.setMinimum(self.u.sB_start.value()) self.u.progressBar.setValue(self.u.sB_start.value()) # self.u.progressBar.setValue(self.u.sB_start) self.N = self.u.progressBar.value() self.u.progressBar.setMaximum(self.u.sB_End.value()) self.timer.start(1, self) else: msg = qt.QMessageBox() msg.setText('Something wrong happened...') msg.setWindowTitle("!Error!") msg.setDetailedText( 'The directory or/and File header is/are empty!') msg.setStandardButtons(qt.QMessageBox.Ok | qt.QMessageBox.Cancel) msg.exec_()
def initializeGL(self): if hasattr(self, 'windowHandle'): # Qt 5 self._devicePixelRatio = self.windowHandle().devicePixelRatio() if self._devicePixelRatio != 1.0: _logger.info('High DPI support, devicePixelRatio = %f', self._devicePixelRatio) # Check if OpenGL2 is available versionflags = self.format().openGLVersionFlags() self._isOpenGL21 = bool(versionflags & qt.QGLFormat.OpenGL_Version_2_1) if not self._isOpenGL21: _logger.error('3D rendering is disabled: OpenGL 2.1 not available') messageBox = qt.QMessageBox(parent=self) messageBox.setIcon(qt.QMessageBox.Critical) messageBox.setWindowTitle('Error') messageBox.setText('3D rendering is disabled.\n\n' 'Reason: OpenGL 2.1 is not available.') messageBox.addButton(qt.QMessageBox.Ok) messageBox.setWindowModality(qt.Qt.WindowModal) messageBox.setAttribute(qt.Qt.WA_DeleteOnClose) messageBox.show()
def doSaveProject(self, res): fname = res[0][0] if not fname.endswith('.pspj'): fname += '.pspj' try: with open(fname, 'w') as f: f.write('try') except OSError: msg = qt.QMessageBox() msg.setIcon(qt.QMessageBox.Critical) msg.critical(self, "Cannot write file", "Invalid file name {0}".format(fname)) return self.save_project(fname) for i, (name, node) in enumerate(csi.nodes.items()): node.widget.saveGraph(fname, i, name) if len(res) < 5: return saveNodes, saveTypes, saveScriptMpl, saveScriptSilx = res[1:5] plots, h5plots = self.save_data(fname, saveNodes, saveTypes) if saveScriptMpl: self.save_script(fname, plots, h5plots, 'mpl') if saveScriptSilx: self.save_script(fname, plots, h5plots, 'silx')
def dropMimeData(self, mimedata, action, row, column, parent): if mimedata.hasFormat(cco.MIME_TYPE_DATA): toItem = parent.internalPointer() if toItem is None: toItem = csi.dataRootItem newParentItem, newRow = toItem, toItem.child_count() parents = [] else: newParentItem, newRow = toItem.parentItem, toItem.row() parents = [toItem.parentItem] rowss = pickle.loads(mimedata.data(cco.MIME_TYPE_DATA)) dropedItems = [] for rows in rowss: parentItem = self.rootItem for r in reversed(rows): item = parentItem.child(r) parentItem = item dropedItems.append(item) if item.parentItem not in parents: parents.append(item.parentItem) for item in dropedItems: if item.is_ancestor_of(toItem): msg = qt.QMessageBox() msg.setIcon(qt.QMessageBox.Warning) msg.setText("Cannot drop a group onto its child. Ignored") msg.setWindowTitle("Illegal drop") msg.setStandardButtons(qt.QMessageBox.Close) msg.exec_() return False self.beginResetModel() if toItem is csi.dataRootItem: rdropedItems = dropedItems else: rdropedItems = reversed(dropedItems) for item in rdropedItems: oldParentItem, oldRow = item.parentItem, item.row() if newParentItem is oldParentItem: sibl = newParentItem.childItems sibl.insert(newRow, sibl.pop(oldRow)) else: newParentItem.childItems.insert(newRow, item) item.parentItem = newParentItem del oldParentItem.childItems[oldRow] if oldParentItem.child_count() == 0: oldParentItem.delete() self.endResetModel() for parent in parents: parent.init_colors() self.dataChanged.emit(qt.QModelIndex(), qt.QModelIndex()) self.needReplot.emit() return True elif mimedata.hasFormat(cco.MIME_TYPE_TEXT) or \ mimedata.hasFormat(cco.MIME_TYPE_HDF5): toItem = parent.internalPointer() if mimedata.hasFormat(cco.MIME_TYPE_TEXT): urls = [url.toLocalFile() for url in reversed(mimedata.urls())] else: urls = pickle.loads(mimedata.data(cco.MIME_TYPE_HDF5))[::-1] if toItem is None: toItem = csi.dataRootItem urls = urls[::-1] if toItem.child_count() > 0: # is a group parentItem, insertAt = toItem, None else: parentItem, insertAt = toItem.parentItem, toItem.row() if csi.currentNode is None: return False node = csi.currentNode if hasattr(node, 'widget'): items = node.widget.loadFiles(urls, parentItem, insertAt) # if DEBUG > 0: # if items is not None: # for item in items: # item.colorTag = 3 return True else: return False
def loadFiles(self, fileNamesFull=None, parentItem=None, insertAt=None): def times(n): return " ({0} times)".format(n) if n > 1 else "" selectedIndexes = self.files.selectionModel().selectedRows() selectedIndex = selectedIndexes[0] dataStruct = selectedIndex.data(gft.LOAD_DATASET_ROLE) if dataStruct is None: return colRecs, df = dataStruct # spectraInOneFile = 1 # for col in colRecs: # col is a list of (expr, d[xx]-expr, data-keys) # spectraInOneFile = max(spectraInOneFile, len(col)) # if spectraInOneFile > 1: # colMany = [] # for icol, col in enumerate(colRecs): # if len(col) not in [1, spectraInOneFile]: # msg = qt.QMessageBox() # msg.setIcon(qt.QMessageBox.Question) # res = msg.critical( # self, "Cannot load data", # "Lists of different lengths found") # return # if len(col) == spectraInOneFile: # colMany.append(icol) # if not colMany: # return if isinstance(fileNamesFull, qt.QModelIndex): if qt.QFileInfo( self.files.model().filePath(fileNamesFull)).isDir(): return fileNamesFull = None if not fileNamesFull: sIndexes = self.files.selectionModel().selectedRows() nodeType = self.files.model().nodeType(sIndexes[0]) if nodeType == gft.NODE_FS: fileNamesFull = \ [self.files.model().filePath(i) for i in sIndexes] else: # FileTreeView.NODE_HDF5, FileTreeView.NODE_HDF5_HEAD fileNamesFull = \ [self.files.model().getHDF5FullPath(i) for i in sIndexes] fileNames = [osp.normcase(nf) for nf in fileNamesFull] allLoadedItemNames = [] for d in csi.allLoadedItems: lfn = d.madeOf[5:] if d.madeOf.startswith('silx:') else d.madeOf lfns = osp.normcase(osp.abspath(lfn)) if d.madeOf.startswith('silx:'): lfns = 'silx:' + lfns allLoadedItemNames.append(lfns) allLoadedItemsCount = Counter(allLoadedItemNames) duplicates, duplicatesN = [], [] fileNamesFullN = [] for fname, fnameFull in zip(fileNames, fileNamesFull): n = allLoadedItemsCount[osp.normcase(fnameFull)] if n > 0: duplicates.append(fnameFull) duplicatesN.append(n) fileNamesFullN.append(n) if duplicates: duplicatesNStr =\ [dup + times(n) for dup, n in zip(duplicates, duplicatesN)] st1, st2, st3, st4 =\ ('This', '', 'is', 'it') if len(duplicates) == 1 else\ ('These', 's', 'are', 'them') msg = qt.QMessageBox() msg.setIcon(qt.QMessageBox.Question) res = msg.question( self, "Already in the data list", "{0} file{1} {2} already loaded:\n{3}".format( st1, st2, st3, '\n'.join(duplicatesNStr)) + "\nDo you want to load {0} gain?".format(st4), qt.QMessageBox.Yes | qt.QMessageBox.No, qt.QMessageBox.Yes) if res == qt.QMessageBox.No: return if parentItem is None: if csi.selectedItems: parentItem = csi.selectedItems[0].parentItem else: parentItem = csi.dataRootItem # !!! TODO !!! # here the column format is taken from the present state of # ColumnFormatWidget. Should be automatically detected from # file format # df['dataSource'] = [col[0][0] for col in colRecs] items = csi.model.importData(fileNamesFull, parentItem, insertAt, dataFormat=df, originNode=self.node) # if spectraInOneFile == 1: # df['dataSource'] = [col[0][0] for col in colRecs] # items = csi.model.importData( # fileNamesFull, parentItem, insertAt, dataFormat=df, # originNode=self.node) # else: # keys = [col[2][0] for col in colRecs[colMany[0]]] # cs = keys[0] # for key in keys[1:]: # cs = cco.common_substring(cs, key) # colNames = [key[len(cs):] for key in keys] # for fname in fileNamesFull: # basename = osp.basename(fname) # groupName = osp.splitext(basename)[0] # if '::' in fname: # h5name = osp.splitext(osp.basename( # fname[:fname.find('::')]))[0] # groupName = '/'.join([h5name, groupName]) # group, = csi.model.importData(groupName, parentItem, insertAt) # for i, colName in enumerate(colNames): # df['dataSource'] = \ # [col[i][0] if len(col) > 1 else col[0][0] # for col in colRecs] # csi.model.importData( # fname, group, dataFormat=df, # alias='{0}_{1}'.format(groupName, colName), # originNode=self.node) # items = group, mode = qt.QItemSelectionModel.Select | qt.QItemSelectionModel.Rows for item in items: row = item.row() index = csi.model.createIndex(row, 0, item) csi.selectionModel.select(index, mode)
def _pluginClicked(self): actionNames = [] menu = qt.QMenu(self) menu.addAction("Reload Plugins") actionNames.append("Reload Plugins") menu.addAction("Set User Plugin Directory") actionNames.append("Set User Plugin Directory") if _logger.getEffectiveLevel() == logging.DEBUG: text = "Toggle DEBUG mode OFF" else: text = "Toggle DEBUG mode ON" menu.addAction(text) menu.addSeparator() actionNames.append(text) callableKeys = ["Dummy0", "Dummy1", "Dummy2"] pluginInstances = self.pluginInstanceDict for pluginName in self.pluginList: if pluginName in ["PyMcaPlugins.Plugin1DBase", "Plugin1DBase"]: continue module = sys.modules[pluginName] if hasattr(module, 'MENU_TEXT'): text = module.MENU_TEXT else: text = os.path.basename(module.__file__) if text.endswith('.pyc'): text = text[:-4] elif text.endswith('.py'): text = text[:-3] methods = pluginInstances[pluginName].getMethods( plottype=self.plot._plotType) if not len(methods): continue elif len(methods) == 1: pixmap = pluginInstances[pluginName].getMethodPixmap( methods[0]) tip = pluginInstances[pluginName].getMethodToolTip(methods[0]) if pixmap is not None: action = qt.QAction(qt.QIcon(qt.QPixmap(pixmap)), text, self) else: action = qt.QAction(text, self) if tip is not None: action.setToolTip(tip) menu.addAction(action) else: menu.addAction(text) actionNames.append(text) callableKeys.append(pluginName) menu.hovered.connect(self._actionHovered) a = menu.exec_(qt.QCursor.pos()) if a is None: return None idx = actionNames.index(a.text()) if a.text() == "Reload Plugins": n, message = self.getPlugins(exceptions=True) if n < 1: msg = qt.QMessageBox(self) msg.setIcon(qt.QMessageBox.Information) msg.setWindowTitle("No plugins") msg.setInformativeText(" Problem loading plugins ") msg.setDetailedText(message) msg.exec_() return if a.text() == "Set User Plugin Directory": dirName = qt.QFileDialog.getExistingDirectory( self, "Enter user plugins directory", os.getcwd()) if len(dirName): pluginsDir = self.getPluginDirectoryList() pluginsDirList = [pluginsDir[0], dirName] self.setPluginDirectoryList(pluginsDirList) return if "Toggle DEBUG mode" in a.text(): _toggleLogger() key = callableKeys[idx] methods = pluginInstances[key].getMethods(plottype=self.plot._plotType) if len(methods) == 1: idx = 0 else: actionNames = [] # allow the plugin designer to specify the order #methods.sort() menu = qt.QMenu(self) for method in methods: text = method pixmap = pluginInstances[key].getMethodPixmap(method) tip = pluginInstances[key].getMethodToolTip(method) if pixmap is not None: action = qt.QAction(qt.QIcon(qt.QPixmap(pixmap)), text, self) else: action = qt.QAction(text, self) if tip is not None: action.setToolTip(tip) menu.addAction(action) actionNames.append((text, pixmap, tip, action)) #qt.QObject.connect(menu, qt.SIGNAL("hovered(QAction *)"), self._actionHovered) menu.hovered.connect(self._actionHovered) a = menu.exec_(qt.QCursor.pos()) if a is None: return None idx = -1 for action in actionNames: if a.text() == action[0]: idx = actionNames.index(action) try: pluginInstances[key].applyMethod(methods[idx]) except: msg = qt.QMessageBox(self) msg.setIcon(qt.QMessageBox.Critical) msg.setWindowTitle("Plugin error") msg.setText("An error has occured while executing the plugin:") msg.setInformativeText(str(sys.exc_info()[1])) msg.setDetailedText(traceback.format_exc()) msg.exec_()