From 83948d316d77f7ea06567f6bcefdc9760d48067b Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Thu, 11 Oct 2018 07:39:13 -0400 Subject: [PATCH 01/11] Check for ui file existence and report errror Refs #23762 --- qt/python/mantidqt/utils/qt/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qt/python/mantidqt/utils/qt/__init__.py b/qt/python/mantidqt/utils/qt/__init__.py index a622bdb6e198..dd491474b05b 100644 --- a/qt/python/mantidqt/utils/qt/__init__.py +++ b/qt/python/mantidqt/utils/qt/__init__.py @@ -77,6 +77,10 @@ def load_ui(caller_filename, ui_relfilename, baseinstance=None): return the form class """ filepath = osp.join(osp.dirname(caller_filename), ui_relfilename) + if not osp.exists(filepath): + raise ImportError('File "{}" does not exist'.format(filepath)) + if not osp.isfile(filepath): + raise ImportError('File "{}" is not a file'.format(filepath)) if baseinstance is not None: return loadUi(filepath, baseinstance=baseinstance) else: From 427a16e29872ac7e8a37368b25eb7350fb0e0c40 Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Thu, 11 Oct 2018 15:36:48 -0400 Subject: [PATCH 02/11] Add function to load ui files This is a duplicate of the one in mantidqt and should go away. --- MantidPlot/mantidplot.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/MantidPlot/mantidplot.py b/MantidPlot/mantidplot.py index c04391e2dc77..995893ed0c97 100644 --- a/MantidPlot/mantidplot.py +++ b/MantidPlot/mantidplot.py @@ -13,8 +13,24 @@ from __future__ import (absolute_import, division, print_function) +import os.path as osp import pymantidplot from pymantidplot import * # and the old qtiplot stuff import pymantidplot.qtiplot + +def load_ui(caller_filename, ui_relfilename, baseinstance=None): + '''This is copied from mantidqt.utils.qt and should be deprecated as + soon as possible.''' + from qtpy.uic import loadUi, loadUiType # noqa + + filepath = osp.join(osp.dirname(caller_filename), ui_relfilename) + if not osp.exists(filepath): + raise ImportError('File "{}" does not exist'.format(filepath)) + if not osp.isfile(filepath): + raise ImportError('File "{}" is not a file'.format(filepath)) + if baseinstance is not None: + return loadUi(filepath, baseinstance=baseinstance) + else: + return loadUiType(filepath) From a40651535fb9eeb7c7306f709b9725a8940e0323 Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Thu, 11 Oct 2018 16:22:46 -0400 Subject: [PATCH 03/11] Make the FilterEventGui qt4/qt5 compatible Replacing lots of things with qtpy and abstracting off the backend running in matplotlib --- scripts/CMakeLists.txt | 4 +- scripts/FilterEvents.py | 30 +++- scripts/FilterEvents/CMakeLists.txt | 11 -- scripts/FilterEvents/ErrorMessage.ui | 230 ------------------------ scripts/FilterEvents/MplFigureCanvas.py | 28 ++- scripts/FilterEvents/eventFilterGUI.py | 148 ++++++--------- 6 files changed, 97 insertions(+), 354 deletions(-) delete mode 100644 scripts/FilterEvents/CMakeLists.txt delete mode 100644 scripts/FilterEvents/ErrorMessage.ui diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index e8f37ca00141..850c941cfca3 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -1,6 +1,6 @@ # Subdirectories from which ui files need processing to py files -add_subdirectory(FilterEvents) +# FilterEvents doesn't need any special work add_subdirectory(Interface/ui) add_subdirectory(TofConverter) add_subdirectory(HFIR_4Circle_Reduction) @@ -8,7 +8,6 @@ add_subdirectory(ErrorReporter) # Chain all required interface custom targets into CompilePyUI add_custom_target(CompilePyUI DEPENDS - CompileUIFilterEvents CompileUITofConverter CompileUIUI CompileUIHFIR_4Circle_Reduction @@ -17,7 +16,6 @@ add_custom_target(CompilePyUI DEPENDS # Put them into the 'CompileUI' folder or group in VS and the like, for convenience set_property ( TARGET CompilePyUI PROPERTY FOLDER "CompilePyUI" ) -set_property ( TARGET CompileUIFilterEvents PROPERTY FOLDER "CompilePyUI" ) set_property ( TARGET CompileUITofConverter PROPERTY FOLDER "CompilePyUI" ) set_property ( TARGET CompileUIUI PROPERTY FOLDER "CompilePyUI" ) set_property ( TARGET CompileUIHFIR_4Circle_Reduction PROPERTY FOLDER "CompilePyUI" ) diff --git a/scripts/FilterEvents.py b/scripts/FilterEvents.py index 09f5733e3e10..12f79aecb1a0 100644 --- a/scripts/FilterEvents.py +++ b/scripts/FilterEvents.py @@ -6,21 +6,33 @@ # SPDX - License - Identifier: GPL - 3.0 + #pylint: disable=invalid-name from __future__ import (absolute_import, division, print_function) -from FilterEvents import eventFilterGUI -from PyQt4 import QtGui +from qtpy.QtWidgets import (QApplication) # noqa import sys - +# set the backend for matplotlib to use +import matplotlib +if not matplotlib.get_backend().startswith('module://'): + from qtpy import PYQT4, PYQT5 + if PYQT4: + matplotlib.use('Qt4Agg') + print('Qt4Agg') + elif PYQT5: + matplotlib.use('Qt5Agg') + print('Qt5Agg') + else: + raise RuntimeError('Do not know which matplotlib backend to set') +from FilterEvents import eventFilterGUI # noqa def qapp(): - if QtGui.QApplication.instance(): - _app = QtGui.QApplication.instance() + app = QApplication.instance() + if app: + return app, app.applicationName().lower().startswith('mantid') else: - _app = QtGui.QApplication(sys.argv) - return _app + return QApplication(sys.argv), False -app = qapp() +app, within_mantid = qapp() reducer = eventFilterGUI.MainWindow() #the main ui class in this file is called MainWindow reducer.show() -app.exec_() +if not within_mantid: + sys.exit(app.exec_()) diff --git a/scripts/FilterEvents/CMakeLists.txt b/scripts/FilterEvents/CMakeLists.txt deleted file mode 100644 index 81b5a396dde8..000000000000 --- a/scripts/FilterEvents/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -include(UiToPy) - -# List of UIs to Auto convert -set( UI_FILES - ErrorMessage.ui - MainWindow.ui -) - -UiToPy( UI_FILES CompileUIFilterEvents) - - diff --git a/scripts/FilterEvents/ErrorMessage.ui b/scripts/FilterEvents/ErrorMessage.ui deleted file mode 100644 index 9c54a0c41fcf..000000000000 --- a/scripts/FilterEvents/ErrorMessage.ui +++ /dev/null @@ -1,230 +0,0 @@ - - - Dialog - - - - 0 - 0 - 400 - 225 - - - - - 40 - 20 - - - - Error - - - - - - Qt::Vertical - - - - 17 - 37 - - - - - - - - - - QLayout::SetMinimumSize - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 80 - 40 - - - - - 16 - 75 - true - - - - <html><head/><body><p><span style=" color:#ff0000;">Error</span></p></body></html> - - - Qt::RichText - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - QLayout::SetMinimumSize - - - - - Qt::Horizontal - - - - 41 - 146 - - - - - - - - - 0 - 0 - - - - - 300 - 80 - - - - TextLabel - - - Qt::RichText - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - QLayout::SetMinimumSize - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Close - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - diff --git a/scripts/FilterEvents/MplFigureCanvas.py b/scripts/FilterEvents/MplFigureCanvas.py index 5b515ba21ae8..3888838278b5 100644 --- a/scripts/FilterEvents/MplFigureCanvas.py +++ b/scripts/FilterEvents/MplFigureCanvas.py @@ -6,9 +6,29 @@ # SPDX - License - Identifier: GPL - 3.0 + #pylint: disable=invalid-name from __future__ import (absolute_import, division, print_function) -from PyQt4 import QtGui +from qtpy import PYQT4, PYQT5 +from qtpy.QtWidgets import QSizePolicy + +import matplotlib +backend = matplotlib.get_backend() +if backend.startswith('module://'): + if backend.endswith('qt4agg'): + backend = 'Qt4Agg' + elif backend.endswith('workbench') or backend.endswith('qt5agg'): + backend = 'Qt5Agg' +else: # is this part necessary? + if PYQT4: + backend = 'Qt4Agg' + elif PYQT5: + backend = 'Qt5Agg' + +if backend == 'Qt4Agg': + from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas +elif backend == 'Qt5Agg': + from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas +else: + raise RuntimeError('Unrecognized backend {}'.format(backend)) -from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure @@ -29,8 +49,8 @@ def __init__(self, parent): self.setParent(parent) # Set size policy to be able to expanding and resizable with frame - FigureCanvas.setSizePolicy(self, QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Expanding) + FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, + QSizePolicy.Expanding) FigureCanvas.updateGeometry(self) diff --git a/scripts/FilterEvents/eventFilterGUI.py b/scripts/FilterEvents/eventFilterGUI.py index 6677164f18cd..9322a1932e3c 100644 --- a/scripts/FilterEvents/eventFilterGUI.py +++ b/scripts/FilterEvents/eventFilterGUI.py @@ -8,10 +8,8 @@ from __future__ import (absolute_import, division, print_function) import numpy -from FilterEvents.ui_MainWindow import Ui_MainWindow #import line for the UI python class -from PyQt4 import QtCore, QtGui -from PyQt4.QtCore import * -from PyQt4.QtGui import * +from qtpy.QtWidgets import (QFileDialog, QMainWindow, QMessageBox, QSlider, QWidget) # noqa +from qtpy.QtGui import (QDoubleValidator) # noqa from matplotlib.pyplot import setp @@ -25,59 +23,19 @@ import os +try: + from mantidqt.utils.qt import load_ui +except ImportError: + Logger("Filter_Events").information('Using legacy ui importer') + from mantidplot import load_ui + HUGE_FAST = 10000 HUGE_PARALLEL = 100000 MAXTIMEBINSIZE = 3000 -try: - _fromUtf8 = QtCore.QString.fromUtf8 -except AttributeError: - def _fromUtf8(s): - return s - - -class MyPopErrorMsg(QWidget): - """ Pop up dialog window - """ - - def __init__(self): - """ Init - """ - import FilterEvents.ui_ErrorMessage as errui - QWidget.__init__(self) - - self.ui = errui.Ui_Dialog() - self.ui.setupUi(self) - QtCore.QObject.connect(self.ui.pushButton_quit, QtCore.SIGNAL('clicked()'), self.quit) - - def setMessage(self, errmsg): - """ Set message - """ - self.ui.label_errmsg.setWordWrap(True) - self.ui.label_errmsg.setText(errmsg) - return - - def quit(self): - """ Quit - """ - self.close() - - return - - def XpaintEvent(self, _): - """ ??? - """ - import FilterEvents.ui_ErrorMessage as errui - - self.ui = errui.Ui_Dialog() - self.ui.setupUi(self) - - return - - -class MainWindow(QtGui.QMainWindow): +class MainWindow(QMainWindow): """ Class of Main Window (top) """ @@ -87,18 +45,17 @@ def __init__(self, parent=None): """ Initialization and set up """ # Base class - QtGui.QMainWindow.__init__(self,parent) + QMainWindow.__init__(self,parent) # Mantid configuration config = ConfigService.Instance() self._instrument = config["default.instrument"] # Central widget - self.centralwidget = QtGui.QWidget(self) + self.centralwidget = QWidget(self) # UI Window (from Qt Designer) - self.ui = Ui_MainWindow() - self.ui.setupUi(self) + self.ui = load_ui(__file__, 'MainWindow.ui', baseinstance=self) self.ui.mainplot = self.ui.graphicsView.getPlot() # Do initialize plotting @@ -129,48 +86,46 @@ def __init__(self, parent=None): self.ui.horizontalSlider.setValue(self._leftSlideValue) self.ui.horizontalSlider.setTracking(True) self.ui.horizontalSlider.setTickPosition(QSlider.NoTicks) - self.connect(self.ui.horizontalSlider, SIGNAL('valueChanged(int)'), self.move_leftSlider) + self.ui.horizontalSlider.valueChanged.connect(self.move_leftSlider) self.ui.horizontalSlider_2.setRange(0, 100) self.ui.horizontalSlider_2.setValue(self._rightSlideValue) self.ui.horizontalSlider_2.setTracking(True) self.ui.horizontalSlider_2.setTickPosition(QSlider.NoTicks) - self.connect(self.ui.horizontalSlider_2, SIGNAL('valueChanged(int)'), self.move_rightSlider) + self.ui.horizontalSlider_2.valueChanged.connect(self.move_rightSlider) # self.connect(self.ui.lineEdit_3, QtCore.SIGNAL("textChanged(QString)"), # self.set_startTime) - self.ui.lineEdit_3.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_3)) - self.connect(self.ui.pushButton_setT0, QtCore.SIGNAL("clicked()"), self.set_startTime) + self.ui.lineEdit_3.setValidator(QDoubleValidator(self.ui.lineEdit_3)) + self.ui.pushButton_setT0.clicked.connect(self.set_startTime) # self.connect(self.ui.lineEdit_4, QtCore.SIGNAL("textChanged(QString)"), # self.set_stopTime) - self.ui.lineEdit_4.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_4)) - self.connect(self.ui.pushButton_setTf, QtCore.SIGNAL("clicked()"), self.set_stopTime) + self.ui.lineEdit_4.setValidator(QDoubleValidator(self.ui.lineEdit_4)) + self.ui.pushButton_setTf.clicked.connect(self.set_stopTime) # File loader self.scanEventWorkspaces() - self.connect(self.ui.pushButton_refreshWS, SIGNAL('clicked()'), self.scanEventWorkspaces) - self.connect(self.ui.pushButton_browse, SIGNAL('clicked()'), self.browse_File) - self.connect(self.ui.pushButton_load, SIGNAL('clicked()'), self.load_File) - self.connect(self.ui.pushButton_3, SIGNAL('clicked()'), self.use_existWS) + self.ui.pushButton_refreshWS.clicked.connect(self.scanEventWorkspaces) + self.ui.pushButton_browse.clicked.connect(self.browse_File) + self.ui.pushButton_load.clicked.connect(self.load_File) + self.ui.pushButton_3.clicked.connect(self.use_existWS) # Set up time - self.ui.lineEdit_3.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_3)) - self.ui.lineEdit_4.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_4)) + self.ui.lineEdit_3.setValidator(QDoubleValidator(self.ui.lineEdit_3)) + self.ui.lineEdit_4.setValidator(QDoubleValidator(self.ui.lineEdit_4)) # Filter by time - self.connect(self.ui.pushButton_filterTime, SIGNAL('clicked()'), self.filterByTime) + self.ui.pushButton_filterTime.clicked.connect(self.filterByTime) # Filter by log value - self.ui.lineEdit_5.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_5)) - self.ui.lineEdit_6.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_6)) - self.ui.lineEdit_7.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_7)) - self.ui.lineEdit_8.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_8)) - self.ui.lineEdit_9.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_9)) + self.ui.lineEdit_5.setValidator(QDoubleValidator(self.ui.lineEdit_5)) + self.ui.lineEdit_6.setValidator(QDoubleValidator(self.ui.lineEdit_6)) + self.ui.lineEdit_7.setValidator(QDoubleValidator(self.ui.lineEdit_7)) + self.ui.lineEdit_8.setValidator(QDoubleValidator(self.ui.lineEdit_8)) + self.ui.lineEdit_9.setValidator(QDoubleValidator(self.ui.lineEdit_9)) - self.connect(self.ui.lineEdit_5, QtCore.SIGNAL("textChanged(QString)"), - self.set_minLogValue) - self.connect(self.ui.lineEdit_6, QtCore.SIGNAL("textChanged(QString)"), - self.set_maxLogValue) + self.ui.lineEdit_5.textChanged.connect(self.set_minLogValue) + self.ui.lineEdit_6.textChanged.connect(self.set_maxLogValue) dirchangeops = ["Both", "Increase", "Decrease"] self.ui.comboBox_4.addItems(dirchangeops) @@ -178,12 +133,12 @@ def __init__(self, parent=None): logboundops = ["Centre", "Left"] self.ui.comboBox_5.addItems(logboundops) - self.connect(self.ui.pushButton_4, SIGNAL('clicked()'), self.plotLogValue) + self.ui.pushButton_4.clicked.connect(self.plotLogValue) - self.connect(self.ui.pushButton_filterLog, SIGNAL('clicked()'), self.filterByLogValue) + self.ui.pushButton_filterLog.clicked.connect(self.filterByLogValue) #Set up help button - self.connect(self.ui.helpBtn, QtCore.SIGNAL('clicked()'), self.helpClicked) + self.ui.helpBtn.clicked.connect(self.helpClicked) # Set up vertical slide self._upperSlideValue = 99 @@ -192,12 +147,12 @@ def __init__(self, parent=None): self.ui.verticalSlider.setRange(0, 100) self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.verticalSlider.setTracking(True) - self.connect(self.ui.verticalSlider, SIGNAL('valueChanged(int)'), self.move_upperSlider) + self.ui.verticalSlider.valueChanged.connect(self.move_upperSlider) self.ui.verticalSlider_2.setRange(0, 100) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) self.ui.verticalSlider_2.setTracking(True) - self.connect(self.ui.verticalSlider_2, SIGNAL('valueChanged(int)'), self.move_lowerSlider) + self.ui.verticalSlider_2.valueChanged.connect(self.move_lowerSlider) # Set up for filtering (advanced setup) self._tofcorrection = False @@ -206,10 +161,10 @@ def __init__(self, parent=None): self.ui.checkBox_from1.setChecked(False) self.ui.checkBox_groupWS.setChecked(True) - self.connect(self.ui.comboBox_tofCorr, SIGNAL('currentIndexChanged(int)'), self.showHideEi) - self.connect(self.ui.pushButton_refreshCorrWSList, SIGNAL('clicked()'), self._searchTableWorkspaces) + self.ui.comboBox_tofCorr.currentIndexChanged.connect(self.showHideEi) + self.ui.pushButton_refreshCorrWSList.clicked.connect(self._searchTableWorkspaces) - self.ui.lineEdit_Ei.setValidator(QtGui.QDoubleValidator(self.ui.lineEdit_Ei)) + self.ui.lineEdit_Ei.setValidator(QDoubleValidator(self.ui.lineEdit_Ei)) self.ui.label_Ei.hide() self.ui.lineEdit_Ei.hide() @@ -242,7 +197,7 @@ def __init__(self, parent=None): # Default self._defaultdir = os.getcwd() - # self.ui.InputVal.setValidator(QtGui.QDoubleValidator(self.ui.InputVal)) + # self.ui.InputVal.setValidator(QDoubleValidator(self.ui.InputVal)) # QtCore.QObject.connect(self.ui.convert, QtCore.SIGNAL("clicked()"), self.convert ) # QtCore.QObject.connect(self.ui.inputUnits, QtCore.SIGNAL("currentIndexChanged(QString)"), self.setInstrumentInputs ) @@ -641,7 +596,7 @@ def set_maxLogValue(self): def browse_File(self): """ Open a file dialog to get file """ - filename = QtGui.QFileDialog.getOpenFileName(self, 'Input File Dialog', + filename = QFileDialog.getOpenFileName(self, 'Input File Dialog', self._defaultdir, "Data (*.nxs *.dat);;All files (*)") self.ui.lineEdit.setText(str(filename)) @@ -662,7 +617,6 @@ def load_File(self): # isabspath = True #else: # isabspath = False - dataws = self._loadFile(str(filename)) if dataws is None: error_msg = "Unable to locate run %s in default directory %s." % (filename, self._defaultdir) @@ -1179,15 +1133,15 @@ def _clearErrorMsg(self): def _setErrorMsg(self, errmsg): """ Clear error message """ - #self.ui.plainTextEdit_ErrorMsg.setPlainText(errmsg) - #self.ui.label_error.show() - - #print "Testing Pop-up Error Message Window: %s" % (errmsg) - self._errMsgWindow = MyPopErrorMsg() - self._errMsgWindow.setMessage(errmsg) - self._errMsgWindow.show() - - return + self._errMsgWindow = QMessageBox() + self._errMsgWindow.setIcon(QMessageBox.Critical) + self._errMsgWindow.setWindowTitle('Error') + self._errMsgWindow.setStandardButtons(QMessageBox.Ok) + self._errMsgWindow.setText(errmsg) + #self._errMsgWindow.show() + result = self._errMsgWindow.exec_() + + return result def helpClicked(self): from pymantidplot.proxies import showCustomInterfaceHelp From 926597b09525061e079213ec992cf97ed4021b3a Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Thu, 11 Oct 2018 16:56:55 -0400 Subject: [PATCH 04/11] Refactor code to reusable functions --- scripts/FilterEvents.py | 25 ++----------- scripts/FilterEvents/MplFigureCanvas.py | 23 +----------- scripts/MPLwidgets.py | 16 +++++++++ scripts/gui_helper.py | 47 +++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 44 deletions(-) create mode 100644 scripts/MPLwidgets.py create mode 100644 scripts/gui_helper.py diff --git a/scripts/FilterEvents.py b/scripts/FilterEvents.py index 12f79aecb1a0..939895c42a7f 100644 --- a/scripts/FilterEvents.py +++ b/scripts/FilterEvents.py @@ -6,31 +6,12 @@ # SPDX - License - Identifier: GPL - 3.0 + #pylint: disable=invalid-name from __future__ import (absolute_import, division, print_function) -from qtpy.QtWidgets import (QApplication) # noqa import sys -# set the backend for matplotlib to use -import matplotlib -if not matplotlib.get_backend().startswith('module://'): - from qtpy import PYQT4, PYQT5 - if PYQT4: - matplotlib.use('Qt4Agg') - print('Qt4Agg') - elif PYQT5: - matplotlib.use('Qt5Agg') - print('Qt5Agg') - else: - raise RuntimeError('Do not know which matplotlib backend to set') +from gui_helper import set_matplotlib_backend, get_qapplication +set_matplotlib_backend() # must be called before anything tries to use matplotlib from FilterEvents import eventFilterGUI # noqa -def qapp(): - app = QApplication.instance() - if app: - return app, app.applicationName().lower().startswith('mantid') - else: - return QApplication(sys.argv), False - - -app, within_mantid = qapp() +app, within_mantid = get_qapplication() reducer = eventFilterGUI.MainWindow() #the main ui class in this file is called MainWindow reducer.show() diff --git a/scripts/FilterEvents/MplFigureCanvas.py b/scripts/FilterEvents/MplFigureCanvas.py index 3888838278b5..766b27f825a6 100644 --- a/scripts/FilterEvents/MplFigureCanvas.py +++ b/scripts/FilterEvents/MplFigureCanvas.py @@ -6,29 +6,8 @@ # SPDX - License - Identifier: GPL - 3.0 + #pylint: disable=invalid-name from __future__ import (absolute_import, division, print_function) -from qtpy import PYQT4, PYQT5 from qtpy.QtWidgets import QSizePolicy - -import matplotlib -backend = matplotlib.get_backend() -if backend.startswith('module://'): - if backend.endswith('qt4agg'): - backend = 'Qt4Agg' - elif backend.endswith('workbench') or backend.endswith('qt5agg'): - backend = 'Qt5Agg' -else: # is this part necessary? - if PYQT4: - backend = 'Qt4Agg' - elif PYQT5: - backend = 'Qt5Agg' - -if backend == 'Qt4Agg': - from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas -elif backend == 'Qt5Agg': - from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas -else: - raise RuntimeError('Unrecognized backend {}'.format(backend)) - +from MPLwidgets import FigureCanvasQTAgg as FigureCanvas from matplotlib.figure import Figure diff --git a/scripts/MPLwidgets.py b/scripts/MPLwidgets.py new file mode 100644 index 000000000000..67b586db707c --- /dev/null +++ b/scripts/MPLwidgets.py @@ -0,0 +1,16 @@ +# Mantid Repository : https://github.com/mantidproject/mantid +# +# Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, +# NScD Oak Ridge National Laboratory, European Spallation Source +# & Institut Laue - Langevin +# SPDX - License - Identifier: GPL - 3.0 + +from __future__ import (absolute_import, division, print_function) +from gui_helper import set_matplotlib_backend + +backend = set_matplotlib_backend() # must be at the top of this file +if backend == 'Qt4Agg': + from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg +elif backend == 'Qt5Agg': + from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg +else: + raise RuntimeError('Unrecognized backend {}'.format(backend)) diff --git a/scripts/gui_helper.py b/scripts/gui_helper.py new file mode 100644 index 000000000000..56c7d083c199 --- /dev/null +++ b/scripts/gui_helper.py @@ -0,0 +1,47 @@ +# Mantid Repository : https://github.com/mantidproject/mantid +# +# Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, +# NScD Oak Ridge National Laboratory, European Spallation Source +# & Institut Laue - Langevin +# SPDX - License - Identifier: GPL - 3.0 + +from __future__ import (absolute_import, division, print_function) +from qtpy.QtWidgets import (QApplication) # noqa +import matplotlib +import sys + +def set_matplotlib_backend(): + '''MUST be called before anything tries to use matplotlib + + This will set the backend if it hasn't been already. It also returns the name of the backend to be the name to + be used for importing the correct matplotlib widgets.''' + backend = matplotlib.get_backend() + if backend.startswith('module://'): + if backend.endswith('qt4agg'): + backend = 'Qt4Agg' + elif backend.endswith('workbench') or backend.endswith('qt5agg'): + backend = 'Qt5Agg' + else: + from qtpy import PYQT4, PYQT5 # noqa + if PYQT4: + backend = 'Qt4Agg' + elif PYQT5: + backend = 'Qt5Agg' + else: + raise RuntimeError('Do not know which matplotlib backend to set') + matplotlib.use(backend) + return backend + +def get_qapplication(): + ''' + app, within_mantid = get_qapplication() + reducer = eventFilterGUI.MainWindow() #the main ui class in this file is called MainWindow + reducer.show() + if not within_mantid: + sys.exit(app.exec_())''' + app = QApplication.instance() + if app: + return app, app.applicationName().lower().startswith('mantid') + else: + return QApplication(sys.argv), False + + From 48401568c1613fe0a62746a6db7211858138ce56 Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Fri, 12 Oct 2018 07:35:33 -0400 Subject: [PATCH 05/11] Import all backend widgets from matplotlib --- scripts/MPLwidgets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/MPLwidgets.py b/scripts/MPLwidgets.py index 67b586db707c..39d35191bfaa 100644 --- a/scripts/MPLwidgets.py +++ b/scripts/MPLwidgets.py @@ -9,8 +9,8 @@ backend = set_matplotlib_backend() # must be at the top of this file if backend == 'Qt4Agg': - from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg + from matplotlib.backends.backend_qt4agg import * elif backend == 'Qt5Agg': - from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg + from matplotlib.backends.backend_qt5agg import * else: raise RuntimeError('Unrecognized backend {}'.format(backend)) From 2af9f74ebdc4360b25381ca04a93f3e46e256bf3 Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Fri, 12 Oct 2018 08:42:48 -0400 Subject: [PATCH 06/11] Fix flake8 and pep8 warnings --- scripts/FilterEvents.py | 2 +- scripts/FilterEvents/eventFilterGUI.py | 170 ++++++++++--------------- scripts/MPLwidgets.py | 6 +- scripts/gui_helper.py | 11 +- 4 files changed, 80 insertions(+), 109 deletions(-) diff --git a/scripts/FilterEvents.py b/scripts/FilterEvents.py index 939895c42a7f..a695b6621447 100644 --- a/scripts/FilterEvents.py +++ b/scripts/FilterEvents.py @@ -4,7 +4,7 @@ # NScD Oak Ridge National Laboratory, European Spallation Source # & Institut Laue - Langevin # SPDX - License - Identifier: GPL - 3.0 + -#pylint: disable=invalid-name +# pylint: disable=invalid-name from __future__ import (absolute_import, division, print_function) import sys from gui_helper import set_matplotlib_backend, get_qapplication diff --git a/scripts/FilterEvents/eventFilterGUI.py b/scripts/FilterEvents/eventFilterGUI.py index 9322a1932e3c..0e46bed2f8f1 100644 --- a/scripts/FilterEvents/eventFilterGUI.py +++ b/scripts/FilterEvents/eventFilterGUI.py @@ -4,7 +4,7 @@ # NScD Oak Ridge National Laboratory, European Spallation Source # & Institut Laue - Langevin # SPDX - License - Identifier: GPL - 3.0 + -#pylint: disable=invalid-name, too-many-lines, too-many-instance-attributes +# pylint: disable=invalid-name, too-many-lines, too-many-instance-attributes from __future__ import (absolute_import, division, print_function) import numpy @@ -34,7 +34,6 @@ MAXTIMEBINSIZE = 3000 - class MainWindow(QMainWindow): """ Class of Main Window (top) """ @@ -45,7 +44,7 @@ def __init__(self, parent=None): """ Initialization and set up """ # Base class - QMainWindow.__init__(self,parent) + QMainWindow.__init__(self, parent) # Mantid configuration config = ConfigService.Instance() @@ -137,7 +136,7 @@ def __init__(self, parent=None): self.ui.pushButton_filterLog.clicked.connect(self.filterByLogValue) - #Set up help button + # Set up help button self.ui.helpBtn.clicked.connect(self.helpClicked) # Set up vertical slide @@ -172,11 +171,6 @@ def __init__(self, parent=None): self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() - # Error message - # self.connect(self.ui.pushButton_clearerror, SIGNAL('clicked()'), self._clearErrorMsg) - # self.ui.plainTextEdit_ErrorMsg.setReadOnly(True) - # self.ui.label_error.hide() - # Set up for workspaces self._dataWS = None self._sampleLogNames = [] @@ -197,17 +191,8 @@ def __init__(self, parent=None): # Default self._defaultdir = os.getcwd() - # self.ui.InputVal.setValidator(QDoubleValidator(self.ui.InputVal)) - - # QtCore.QObject.connect(self.ui.convert, QtCore.SIGNAL("clicked()"), self.convert ) - # QtCore.QObject.connect(self.ui.inputUnits, QtCore.SIGNAL("currentIndexChanged(QString)"), self.setInstrumentInputs ) - # QtCore.QObject.connect(self.ui.outputUnits, QtCore.SIGNAL("currentIndexChanged(QString)"), self.setInstrumentInputs ) - # self.setInstrumentInputs() - - ##defaults - - #register startup - mantid.UsageService.registerFeatureUsage("Interface","EventFilter",False) + # register startup + mantid.UsageService.registerFeatureUsage("Interface", "EventFilter", False) return @@ -287,7 +272,7 @@ def set_startTime(self): newtime0 = float(inps) # Convert to integer slide value - ileftvalue = int( (newtime0-xlim[0])/(xlim[1] - xlim[0])*100 ) + ileftvalue = int((newtime0-xlim[0])/(xlim[1] - xlim[0])*100) debug_msg = "iLeftSlide = %s" % str(ileftvalue) Logger("Filter_Events").debug(debug_msg) @@ -308,7 +293,8 @@ def set_startTime(self): if resetT is True: newtime0 = xlim[0] + ileftvalue*(xlim[1]-xlim[0])*0.01 - info_msg = "Corrected iLeftSlide = %s (vs. right = %s)" % (str(ileftvalue), str(self._rightSlideValue)) + info_msg = 'Corrected iLeftSlide = {} (vs. right = {})'.format(ileftvalue, + self._rightSlideValue) Logger("Filter_Events").information(info_msg) # Move the slide bar (left) @@ -359,8 +345,7 @@ def set_stopTime(self): """ Set the starting time and left slide bar """ inps = str(self.ui.lineEdit_4.text()) - info_msg = "Stopping time = %s" % (inps) - Logger("Filter_Events").information(info_msg) + Logger("Filter_Events").information('Stopping time = {}'.format(inps)) xlim = self.ui.mainplot.get_xlim() if inps == "": @@ -371,9 +356,8 @@ def set_stopTime(self): newtimef = float(inps) # Convert to integer slide value - irightvalue = int( (newtimef-xlim[0])/(xlim[1] - xlim[0])*100 ) - info_msg = "iRightSlide = %s" % str(irightvalue) - Logger("Filter_Events").information(info_msg) + irightvalue = int((newtimef-xlim[0])/(xlim[1] - xlim[0])*100) + Logger("Filter_Events").information('iRightSlide = {}'.format(irightvalue)) # Return if no change if irightvalue == self._rightSlideValue: @@ -415,7 +399,8 @@ def move_lowerSlider(self): Triggered by a change in Qt Widget. NO EVENT is required. """ inewy = self.ui.verticalSlider_2.value() - debug_msg = "LowerSlFider is set with value %s vs. class variable %s" % (str(inewy), str(self._lowerSlideValue)) + debug_msg = 'LowerSlFider is set with value {} vs. class variable {}'.format(inewy, + self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) # Return with no change @@ -453,7 +438,7 @@ def move_lowerSlider(self): def set_minLogValue(self): """ Set the starting time and left slide bar """ - debug_msg = "Minimum Log Value = %s" %(str(self.ui.lineEdit_5.text())) + debug_msg = 'Minimum Log Value = {}'.format(self.ui.lineEdit_5.text()) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() @@ -466,9 +451,8 @@ def set_minLogValue(self): newminY = float(self.ui.lineEdit_5.text()) # Convert to integer slide value - iminlogval = int( (newminY-ylim[0])/(ylim[1] - ylim[0])*100 ) - debug_msg = "ilowerSlide = %s" % str(iminlogval) - Logger("Filter_Events").debug(debug_msg) + iminlogval = int((newminY-ylim[0])/(ylim[1] - ylim[0])*100) + Logger("Filter_Events").debug('ilowerSlide = {}'.format(iminlogval)) # Return if no change if iminlogval == self._lowerSlideValue: @@ -485,15 +469,15 @@ def set_minLogValue(self): newminY = ylim[0] + iminlogval * (ylim[1]-ylim[0]) * 0.01 # Move the vertical line - lowerx = self.ui.mainplot.get_xlim() - lowery = [newminY, newminY] + lowerx = self.ui.mainplot.get_xlim() + lowery = [newminY, newminY] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) self.ui.graphicsView.draw() # Move the slide bar (lower) self._lowerSlideValue = iminlogval - debug_msg = "LineEdit5 set slide to %s" % str(self._lowerSlideValue) + debug_msg = 'LineEdit5 set slide to {}'.format(self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) @@ -523,7 +507,8 @@ def move_upperSlider(self): else: setLineEdit = True - # Move the upper value bar: upperx and uppery are real value (float but not (0,100)) of the figure + # Move the upper value bar: upperx and uppery are + # real value (float but not (0,100)) of the figure ylim = self.ui.mainplot.get_ylim() newy = ylim[0] + inewy*(ylim[1] - ylim[0])*0.01 upperx = self.ui.mainplot.get_xlim() @@ -532,7 +517,7 @@ def move_upperSlider(self): self.ui.graphicsView.draw() - # Change value + # Change value if setLineEdit is True: self.ui.lineEdit_6.setText(str(newy)) self._upperSlideValue = inewy @@ -543,7 +528,7 @@ def set_maxLogValue(self): """ Set maximum log value from line-edit """ inps = str(self.ui.lineEdit_6.text()) - debug_msg = "Maximum Log Value = %s" %(inps) + debug_msg = 'Maximum Log Value = {}'.format(inps) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() @@ -555,8 +540,8 @@ def set_maxLogValue(self): newmaxY = float(inps) # Convert to integer slide value - imaxlogval = int( (newmaxY-ylim[0])/(ylim[1] - ylim[0])*100 ) - debug_msg = "iUpperSlide = %s" % str(imaxlogval) + imaxlogval = int((newmaxY-ylim[0])/(ylim[1] - ylim[0])*100) + debug_msg = 'iUpperSlide = {}'.format(imaxlogval) Logger("Filter_Events").debug(debug_msg) # Return if no change @@ -577,8 +562,8 @@ def set_maxLogValue(self): newmaxY = ylim[0] + imaxlogval * (ylim[1] - ylim[0]) * 0.01 # Move the vertical line - upperx = self.ui.mainplot.get_xlim() - uppery = [newmaxY, newmaxY] + upperx = self.ui.mainplot.get_xlim() + uppery = [newmaxY, newmaxY] setp(self.upperslideline, xdata=upperx, ydata=uppery) self.ui.graphicsView.draw() @@ -597,7 +582,7 @@ def browse_File(self): """ Open a file dialog to get file """ filename = QFileDialog.getOpenFileName(self, 'Input File Dialog', - self._defaultdir, "Data (*.nxs *.dat);;All files (*)") + self._defaultdir, "Data (*.nxs *.dat);;All files (*)") self.ui.lineEdit.setText(str(filename)) @@ -612,14 +597,9 @@ def load_File(self): # Get file name from line editor filename = str(self.ui.lineEdit.text()) - # Find out it is relative path or absolute path - #if os.path.abspath(filename) == filename: - # isabspath = True - #else: - # isabspath = False dataws = self._loadFile(str(filename)) if dataws is None: - error_msg = "Unable to locate run %s in default directory %s." % (filename, self._defaultdir) + error_msg = 'Unable to locate run {} in default directory {}.'.format(filename, self._defaultdir) Logger("Filter_Events").error(error_msg) self._setErrorMsg(error_msg) else: @@ -665,12 +645,12 @@ def plotLogValue(self): error_msg = "Empty log!" Logger("Filter_Events").error(error_msg) - #Convert absolute time to relative time in seconds + # Convert absolute time to relative time in seconds t0 = self._dataWS.getRun().getProperty("proton_charge").times[0] # append 1 more log if original log only has 1 value tf = self._dataWS.getRun().getProperty("proton_charge").times[-1] - vectimes = numpy.append(vectimes,tf) + vectimes = numpy.append(vectimes, tf) vecvalue = numpy.append(vecvalue, vecvalue[-1]) vecreltimes = (vectimes - t0) / numpy.timedelta64(1, 's') @@ -727,9 +707,9 @@ def plotLogValue(self): self.ui.label_logsize.show() self.ui.label_logsizevalue.show() - self.ui.label_meanvalue.setText("%.5e"%(mean)) - self.ui.label_timeAvgValue.setText("%.5e"%(timeavg)) - self.ui.label_freqValue.setText("%.5e"%(freq)) + self.ui.label_meanvalue.setText("%.5e" % (mean)) + self.ui.label_timeAvgValue.setText("%.5e" % (timeavg)) + self.ui.label_freqValue.setText("%.5e" % (freq)) self.ui.label_lognamevalue.setText(logname) self.ui.label_logsizevalue.setText(str(numentries)) @@ -755,8 +735,8 @@ def _importDataWorkspace(self, dataws): # Plot time counts errmsg = self._plotTimeCounts(dataws) if errmsg is not None: - errmsg = "Workspace %s has invalid sample logs for splitting. Loading \ - failure! \n%s\n" % (str(dataws), errmsg) + errmsg = 'Workspace {} has invalid sample logs for splitting. Loading \ + failure! \n{}\n'.format(dataws, errmsg) self._setErrorMsg(errmsg) return False @@ -825,12 +805,12 @@ def _loadFile(self, filename): # Construct a file name from run number runnumber = int(filename) if runnumber <= 0: - error_msg = "Run number cannot be less or equal to zero. User gives %s. " % (filename) + error_msg = 'Run number cannot be less or equal to zero. User gives {}.'.format(filename) Logger("Filter_Events").error(error_msg) return None else: ishort = config.getInstrument(self._instrument).shortName() - filename = "%s_%s" %(ishort, filename) + filename = '{}_{}'.format(ishort, filename) wsname = filename + "_event" elif filename.count(".") > 0: @@ -844,17 +824,17 @@ def _loadFile(self, filename): if str_runnumber.isdigit() is True and int(str_runnumber) > 0: # Accepted format ishort = config.getInstrument(iname).shortName() - wsname = "%s_%s_event" % (ishort, str_runnumber) + wsname = '{}_{}_event'.format(ishort, str_runnumber) else: # Non-supported - error_msg = "File name / run number in such format %s is not supported. " % (filename) + error_msg = 'File name / run number in such format {} is not supported.'.format(filename) Logger("Filter_Events").error(error_msg) return None else: # Unsupported format - error_msg = "File name / run number in such format %s is not supported. " % (filename) + error_msg = 'File name / run number in such format {} is not supported.'.format(filename) Logger("Filter_Events").error(error_msg) return None @@ -895,11 +875,11 @@ def _plotTimeCounts(self, wksp): if timeres < 1.0: timeres = 1.0 - sumwsname = "_Summed_%s"%(str(wksp)) + sumwsname = '_Summed_{}'.format(wksp) if AnalysisDataService.doesExist(sumwsname) is False: sumws = api.SumSpectra(InputWorkspace=wksp, OutputWorkspace=sumwsname) - sumws = api.RebinByPulseTimes(InputWorkspace=sumws, OutputWorkspace = sumwsname, - Params="%f"%(timeres)) + sumws = api.RebinByPulseTimes(InputWorkspace=sumws, OutputWorkspace=sumwsname, + Params='{}'.format(timeres)) sumws = api.ConvertToPointData(InputWorkspace=sumws, OutputWorkspace=sumwsname) else: sumws = AnalysisDataService.retrieve(sumwsname) @@ -958,13 +938,13 @@ def filterByTime(self): title = str(self.ui.lineEdit_title.text()) fastLog = self.ui.checkBox_fastLog.isChecked() - splitws, infows = api.GenerateEventsFilter( - InputWorkspace = self._dataWS, - UnitOfTime = "Seconds", - TitleOfSplitters = title, - OutputWorkspace = splitwsname, - FastLog = fastLog, - InformationWorkspace = splitinfowsname, **kwargs) + splitws, infows = api.GenerateEventsFilter(InputWorkspace=self._dataWS, + UnitOfTime="Seconds", + TitleOfSplitters=title, + OutputWorkspace=splitwsname, + FastLog=fastLog, + InformationWorkspace=splitinfowsname, + **kwargs) self.splitWksp(splitws, infows) @@ -1019,14 +999,14 @@ def filterByLogValue(self): title = str(self.ui.lineEdit_title.text()) - splitws, infows = api.GenerateEventsFilter( - InputWorkspace = self._dataWS, - UnitOfTime = "Seconds", - TitleOfSplitters = title, - OutputWorkspace = splitwsname, - LogName = samplelog, - FastLog = fastLog, - InformationWorkspace = splitinfowsname, **kwargs) + splitws, infows = api.GenerateEventsFilter(InputWorkspace=self._dataWS, + UnitOfTime="Seconds", + TitleOfSplitters=title, + OutputWorkspace=splitwsname, + LogName=samplelog, + FastLog=fastLog, + InformationWorkspace=splitinfowsname, + **kwargs) try: self.splitWksp(splitws, infows) @@ -1060,18 +1040,17 @@ def splitWksp(self, splitws, infows): outbasewsname = "tempsplitted" self.ui.lineEdit_outwsname.setText(outbasewsname) - api.FilterEvents( - InputWorkspace = self._dataWS, - SplitterWorkspace = splitws, - InformationWorkspace = infows, - OutputWorkspaceBaseName = outbasewsname, - GroupWorkspaces = dogroupws, - FilterByPulseTime = filterbypulse, - CorrectionToSample = corr2sample, - SpectrumWithoutDetector = how2skip, - SplitSampleLogs = splitsamplelog, - OutputWorkspaceIndexedFrom1 = startfrom1, - OutputTOFCorrectionWorkspace = 'TOFCorrTable', **kwargs) + api.FilterEvents(InputWorkspace=self._dataWS, + SplitterWorkspace=splitws, + InformationWorkspace=infows, + OutputWorkspaceBaseName=outbasewsname, + GroupWorkspaces=dogroupws, + FilterByPulseTime=filterbypulse, + CorrectionToSample=corr2sample, + SpectrumWithoutDetector=how2skip, + SplitSampleLogs=splitsamplelog, + OutputWorkspaceIndexedFrom1=startfrom1, + OutputTOFCorrectionWorkspace='TOFCorrTable', **kwargs) return @@ -1122,14 +1101,6 @@ def _searchTableWorkspaces(self): return - def _clearErrorMsg(self): - """ Clear error message - """ - #self.ui.plainTextEdit_ErrorMsg.setPlainText("") - #self.ui.label_error.hide() - - return - def _setErrorMsg(self, errmsg): """ Clear error message """ @@ -1138,7 +1109,6 @@ def _setErrorMsg(self, errmsg): self._errMsgWindow.setWindowTitle('Error') self._errMsgWindow.setStandardButtons(QMessageBox.Ok) self._errMsgWindow.setText(errmsg) - #self._errMsgWindow.show() result = self._errMsgWindow.exec_() return result diff --git a/scripts/MPLwidgets.py b/scripts/MPLwidgets.py index 39d35191bfaa..fe5e3f495d3d 100644 --- a/scripts/MPLwidgets.py +++ b/scripts/MPLwidgets.py @@ -7,10 +7,10 @@ from __future__ import (absolute_import, division, print_function) from gui_helper import set_matplotlib_backend -backend = set_matplotlib_backend() # must be at the top of this file +backend = set_matplotlib_backend() # must be at the top of this file if backend == 'Qt4Agg': - from matplotlib.backends.backend_qt4agg import * + from matplotlib.backends.backend_qt4agg import * # noqa elif backend == 'Qt5Agg': - from matplotlib.backends.backend_qt5agg import * + from matplotlib.backends.backend_qt5agg import * # noqa else: raise RuntimeError('Unrecognized backend {}'.format(backend)) diff --git a/scripts/gui_helper.py b/scripts/gui_helper.py index 56c7d083c199..0d1296e423c5 100644 --- a/scripts/gui_helper.py +++ b/scripts/gui_helper.py @@ -9,11 +9,13 @@ import matplotlib import sys + def set_matplotlib_backend(): '''MUST be called before anything tries to use matplotlib - This will set the backend if it hasn't been already. It also returns the name of the backend to be the name to - be used for importing the correct matplotlib widgets.''' + This will set the backend if it hasn't been already. It also returns + the name of the backend to be the name to be used for importing the + correct matplotlib widgets.''' backend = matplotlib.get_backend() if backend.startswith('module://'): if backend.endswith('qt4agg'): @@ -31,10 +33,11 @@ def set_matplotlib_backend(): matplotlib.use(backend) return backend + def get_qapplication(): ''' app, within_mantid = get_qapplication() - reducer = eventFilterGUI.MainWindow() #the main ui class in this file is called MainWindow + reducer = eventFilterGUI.MainWindow() # the main ui class in this file reducer.show() if not within_mantid: sys.exit(app.exec_())''' @@ -43,5 +46,3 @@ def get_qapplication(): return app, app.applicationName().lower().startswith('mantid') else: return QApplication(sys.argv), False - - From 394c37677ddb4370bd50ae15d9008ca278ed1431 Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Fri, 12 Oct 2018 08:53:30 -0400 Subject: [PATCH 07/11] Add FilterEvents to interfaces menu --- .../workbench/workbench/app/mainwindow.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/qt/applications/workbench/workbench/app/mainwindow.py b/qt/applications/workbench/workbench/app/mainwindow.py index b14975d72e1e..f3322e952718 100644 --- a/qt/applications/workbench/workbench/app/mainwindow.py +++ b/qt/applications/workbench/workbench/app/mainwindow.py @@ -250,13 +250,8 @@ def populate_menus(self): add_actions(self.file_menu, self.file_menu_actions) add_actions(self.view_menu, self.view_menu_actions) - def launchCustomGUI(self, name): - try: - importlib.import_module(name) - except ImportError: - from mantid.kernel import logger - logger.error(str('Failed to load {} interface'.format(name))) # TODO logger should accept unicode - raise + def launchCustomGUI(self, script): + execfile(script) def populateAfterMantidImport(self): from mantid.kernel import ConfigService, logger @@ -266,16 +261,18 @@ def populateAfterMantidImport(self): # list of custom interfaces that have been made qt4/qt5 compatible # TODO need to make *anything* compatible - GUI_WHITELIST = [] + GUI_WHITELIST = ['FilterEvents.py'] # detect the python interfaces interfaces = {} for item in items: - key,scriptname = item.split('/') + key, scriptname = item.split('/') + # TODO logger should accept unicode if not os.path.exists(os.path.join(interface_dir, scriptname)): - logger.warning('Failed to find script "{}" in "{}"'.format(scriptname, interface_dir)) + logger.warning(str('Failed to find script "{}" in "{}"'.format(scriptname, interface_dir))) continue if scriptname not in GUI_WHITELIST: + logger.information(str('Not adding gui "{}"'.format(scriptname))) continue temp = interfaces.get(key, []) temp.append(scriptname) @@ -290,8 +287,8 @@ def populateAfterMantidImport(self): names.sort() for name in names: action = submenu.addAction(name.replace('.py', '').replace('_', ' ')) - script = name.replace('.py', '') - action.triggered.connect(lambda checked, script=script:self.launchCustomGUI(script)) + script = os.path.join(interface_dir, name) + action.triggered.connect(lambda checked, script=script: self.launchCustomGUI(script)) def add_dockwidget(self, plugin): """Create a dockwidget around a plugin and add the dock to window""" @@ -380,6 +377,10 @@ def closeEvent(self, event): import matplotlib.pyplot as plt # noqa plt.close('all') + app = QApplication.instance() + if app is not None: + app.closeAllWindows() + event.accept() else: # Cancel was pressed when closing an editor From 9daf519310f185111fc49d967c1fa060255b0342 Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Fri, 12 Oct 2018 10:13:22 -0400 Subject: [PATCH 08/11] Make call python2/3 compatible --- qt/applications/workbench/workbench/app/mainwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qt/applications/workbench/workbench/app/mainwindow.py b/qt/applications/workbench/workbench/app/mainwindow.py index f3322e952718..92b051ab8199 100644 --- a/qt/applications/workbench/workbench/app/mainwindow.py +++ b/qt/applications/workbench/workbench/app/mainwindow.py @@ -251,7 +251,7 @@ def populate_menus(self): add_actions(self.view_menu, self.view_menu_actions) def launchCustomGUI(self, script): - execfile(script) + exec(open(script).read()) def populateAfterMantidImport(self): from mantid.kernel import ConfigService, logger From 9a9f3972f1043bdc514e9689197f996e1f1822bd Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Fri, 12 Oct 2018 10:59:38 -0400 Subject: [PATCH 09/11] Call self rather than parent class --- scripts/FilterEvents/MplFigureCanvas.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/scripts/FilterEvents/MplFigureCanvas.py b/scripts/FilterEvents/MplFigureCanvas.py index 766b27f825a6..069f02a5764c 100644 --- a/scripts/FilterEvents/MplFigureCanvas.py +++ b/scripts/FilterEvents/MplFigureCanvas.py @@ -28,12 +28,9 @@ def __init__(self, parent): self.setParent(parent) # Set size policy to be able to expanding and resizable with frame - FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, - QSizePolicy.Expanding) - - FigureCanvas.updateGeometry(self) - - return + self.setSizePolicy(QSizePolicy.Expanding, + QSizePolicy.Expanding) + self.updateGeometry() def plot(self, x, y): """ Plot a set of data @@ -45,8 +42,6 @@ def plot(self, x, y): self.y = y self.axes.plot(self.x, self.y) - return - def getPlot(self): """ return figure's axes to expose the matplotlib figure to PyQt client """ From 809f3bb864c81044d77aa1c0a9ad486c06105fed Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Mon, 15 Oct 2018 16:33:02 -0400 Subject: [PATCH 10/11] Add matplotlib from python rather than qtcreator --- scripts/FilterEvents/MainWindow.ui | 9 +---- scripts/FilterEvents/MplFigureCanvas.py | 48 ------------------------- scripts/FilterEvents/eventFilterGUI.py | 37 ++++++++++--------- 3 files changed, 22 insertions(+), 72 deletions(-) delete mode 100644 scripts/FilterEvents/MplFigureCanvas.py diff --git a/scripts/FilterEvents/MainWindow.ui b/scripts/FilterEvents/MainWindow.ui index 8689e5a399e6..ca06ab574e57 100644 --- a/scripts/FilterEvents/MainWindow.ui +++ b/scripts/FilterEvents/MainWindow.ui @@ -208,7 +208,7 @@ - + @@ -1326,13 +1326,6 @@ - - - MplFigureCanvas - QGraphicsView -
MplFigureCanvas.h
-
-
pushButton_browse pushButton_load diff --git a/scripts/FilterEvents/MplFigureCanvas.py b/scripts/FilterEvents/MplFigureCanvas.py deleted file mode 100644 index 069f02a5764c..000000000000 --- a/scripts/FilterEvents/MplFigureCanvas.py +++ /dev/null @@ -1,48 +0,0 @@ -# Mantid Repository : https://github.com/mantidproject/mantid -# -# Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI, -# NScD Oak Ridge National Laboratory, European Spallation Source -# & Institut Laue - Langevin -# SPDX - License - Identifier: GPL - 3.0 + -#pylint: disable=invalid-name -from __future__ import (absolute_import, division, print_function) -from qtpy.QtWidgets import QSizePolicy -from MPLwidgets import FigureCanvasQTAgg as FigureCanvas -from matplotlib.figure import Figure - - -class MplFigureCanvas(FigureCanvas): - """ A customized Qt widget for matplotlib figure. - It can be used to replace GraphicsView of QtGui - """ - - def __init__(self, parent): - """ Initialization - """ - # Instantialize matplotlib Figure - self.fig = Figure() - self.axes = self.fig.add_subplot(111) - - # Initialize parent class and set parent - FigureCanvas.__init__(self, self.fig) - self.setParent(parent) - - # Set size policy to be able to expanding and resizable with frame - self.setSizePolicy(QSizePolicy.Expanding, - QSizePolicy.Expanding) - self.updateGeometry() - - def plot(self, x, y): - """ Plot a set of data - Argument: - - x: numpy array X - - y: numpy array Y - """ - self.x = x - self.y = y - self.axes.plot(self.x, self.y) - - def getPlot(self): - """ return figure's axes to expose the matplotlib figure to PyQt client - """ - return self.axes diff --git a/scripts/FilterEvents/eventFilterGUI.py b/scripts/FilterEvents/eventFilterGUI.py index 0e46bed2f8f1..179d355dd617 100644 --- a/scripts/FilterEvents/eventFilterGUI.py +++ b/scripts/FilterEvents/eventFilterGUI.py @@ -8,10 +8,9 @@ from __future__ import (absolute_import, division, print_function) import numpy -from qtpy.QtWidgets import (QFileDialog, QMainWindow, QMessageBox, QSlider, QWidget) # noqa +from qtpy.QtWidgets import (QFileDialog, QMainWindow, QMessageBox, QSlider, QVBoxLayout, QWidget) # noqa from qtpy.QtGui import (QDoubleValidator) # noqa -from matplotlib.pyplot import setp import mantid import mantid.simpleapi as api @@ -20,7 +19,8 @@ from mantid.simpleapi import AnalysisDataService from mantid.kernel import ConfigService - +from MPLwidgets import FigureCanvasQTAgg as FigureCanvas +from matplotlib.pyplot import (Figure, setp) import os try: @@ -55,7 +55,12 @@ def __init__(self, parent=None): # UI Window (from Qt Designer) self.ui = load_ui(__file__, 'MainWindow.ui', baseinstance=self) - self.ui.mainplot = self.ui.graphicsView.getPlot() + mpl_layout = QVBoxLayout() + self.ui.graphicsView.setLayout(mpl_layout) + self.fig = Figure() + self.canvas = FigureCanvas(self.fig) + self.ui.mainplot = self.fig.add_subplot(111, projection='mantid') + mpl_layout.addWidget(self.canvas) # Do initialize plotting vecx, vecy, xlim, ylim = self.computeMock() @@ -75,7 +80,7 @@ def __init__(self, parent=None): lowery = [ylim[0], ylim[0]] self.lowerslideline = self.ui.mainplot.plot(lowerx, lowery, 'g--') - self.ui.graphicsView.mpl_connect('button_press_event', self.on_mouseDownEvent) + self.canvas.mpl_connect('button_press_event', self.on_mouseDownEvent) # Set up horizontal slide (integer) and string value self._leftSlideValue = 0 @@ -246,7 +251,7 @@ def move_leftSlider(self): lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) - self.ui.graphicsView.draw() + self.canvas.draw() # Change value self.ui.lineEdit_3.setText(str(newx)) @@ -305,7 +310,7 @@ def set_startTime(self): lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) - self.ui.graphicsView.draw() + self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider.setValue(self._leftSlideValue) @@ -330,7 +335,7 @@ def move_rightSlider(self): lefty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=leftx, ydata=lefty) - self.ui.graphicsView.draw() + self.canvas.draw() # Change value self.ui.lineEdit_4.setText(str(newx)) @@ -383,7 +388,7 @@ def set_stopTime(self): righty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=rightx, ydata=righty) - self.ui.graphicsView.draw() + self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider_2.setValue(self._rightSlideValue) @@ -424,7 +429,7 @@ def move_lowerSlider(self): lowery = [newy, newy] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) - self.ui.graphicsView.draw() + self.canvas.draw() # Set line edit input if setLineEdit is True: @@ -473,7 +478,7 @@ def set_minLogValue(self): lowery = [newminY, newminY] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) - self.ui.graphicsView.draw() + self.canvas.draw() # Move the slide bar (lower) self._lowerSlideValue = iminlogval @@ -515,7 +520,7 @@ def move_upperSlider(self): uppery = [newy, newy] setp(self.upperslideline, xdata=upperx, ydata=uppery) - self.ui.graphicsView.draw() + self.canvas.draw() # Change value if setLineEdit is True: @@ -566,7 +571,7 @@ def set_maxLogValue(self): uppery = [newmaxY, newmaxY] setp(self.upperslideline, xdata=upperx, ydata=uppery) - self.ui.graphicsView.draw() + self.canvas.draw() # Set the value to upper slider self._upperSlideValue = imaxlogval @@ -685,7 +690,7 @@ def plotLogValue(self): self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.lineEdit_6.setText("") - self.ui.graphicsView.draw() + self.canvas.draw() # Load property's statistic and give suggestion on parallel and fast log timeavg = samplelog.timeAverageValue() @@ -913,7 +918,7 @@ def _plotTimeCounts(self, wksp): newrightx = xmin + (xmax-xmin)*self._rightSlideValue*0.01 setp(self.rightslideline, xdata=[newrightx, newrightx], ydata=newslidery) - self.ui.graphicsView.draw() + self.canvas.draw() return @@ -1145,7 +1150,7 @@ def _resetGUI(self, resetfilerun=False): xlim = self.ui.mainplot.get_xlim() setp(self.lowerslideline, xdata=xlim, ydata=[miny, miny]) setp(self.upperslideline, xdata=xlim, ydata=[maxy, maxy]) - self.ui.graphicsView.draw() + self.canvas.draw() self.ui.lineEdit_7.clear() self.ui.lineEdit_8.clear() From 5e0262e846dab54ce68f8f75487450670426a953 Mon Sep 17 00:00:00 2001 From: Pete Peterson Date: Tue, 16 Oct 2018 09:22:35 -0400 Subject: [PATCH 11/11] Moved call to draw to later in function --- scripts/FilterEvents/eventFilterGUI.py | 56 +------------------------- 1 file changed, 1 insertion(+), 55 deletions(-) diff --git a/scripts/FilterEvents/eventFilterGUI.py b/scripts/FilterEvents/eventFilterGUI.py index 179d355dd617..696c4748b733 100644 --- a/scripts/FilterEvents/eventFilterGUI.py +++ b/scripts/FilterEvents/eventFilterGUI.py @@ -199,8 +199,6 @@ def __init__(self, parent=None): # register startup mantid.UsageService.registerFeatureUsage("Interface", "EventFilter", False) - return - def on_mouseDownEvent(self, event): """ Respond to pick up a value with mouse down event """ @@ -211,8 +209,6 @@ def on_mouseDownEvent(self, event): msg = "You've clicked on a bar with coords:\n %f, %f" % (x, y) QMessageBox.information(self, "Click!", msg) - return - def computeMock(self): """ Compute vecx and vecy as mocking """ @@ -250,7 +246,6 @@ def move_leftSlider(self): leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) - self.canvas.draw() # Change value @@ -260,8 +255,6 @@ def move_leftSlider(self): # Reset the value to original value self.ui.horizontalSlider.setValue(self._leftSlideValue) - return - def set_startTime(self): """ Set the starting time and left slide bar """ @@ -309,7 +302,6 @@ def set_startTime(self): leftx = [newtime0, newtime0] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) - self.canvas.draw() # Set the value to left slider @@ -318,8 +310,6 @@ def set_startTime(self): if resetT is True: self.ui.lineEdit_3.setText(str(newtime0)) - return - def move_rightSlider(self): """ Re-setup left range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. @@ -334,7 +324,6 @@ def move_rightSlider(self): leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=leftx, ydata=lefty) - self.canvas.draw() # Change value @@ -344,8 +333,6 @@ def move_rightSlider(self): # Reset the value self.ui.horizontalSlider_2.setValue(self._rightSlideValue) - return - def set_stopTime(self): """ Set the starting time and left slide bar """ @@ -387,7 +374,6 @@ def set_stopTime(self): rightx = [newtimef, newtimef] righty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=rightx, ydata=righty) - self.canvas.draw() # Set the value to left slider @@ -397,8 +383,6 @@ def set_stopTime(self): if resetT: self.ui.lineEdit_4.setText(str(newtimef)) - return - def move_lowerSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. @@ -428,7 +412,6 @@ def move_lowerSlider(self): lowerx = self.ui.mainplot.get_xlim() lowery = [newy, newy] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) - self.canvas.draw() # Set line edit input @@ -438,8 +421,6 @@ def move_lowerSlider(self): # Reset the class variable self._lowerSlideValue = inewy - return - def set_minLogValue(self): """ Set the starting time and left slide bar """ @@ -477,7 +458,6 @@ def set_minLogValue(self): lowerx = self.ui.mainplot.get_xlim() lowery = [newminY, newminY] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) - self.canvas.draw() # Move the slide bar (lower) @@ -490,8 +470,6 @@ def set_minLogValue(self): if resetL is True: self.ui.lineEdit_5.setText(str(newminY)) - return - def move_upperSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. @@ -519,7 +497,6 @@ def move_upperSlider(self): upperx = self.ui.mainplot.get_xlim() uppery = [newy, newy] setp(self.upperslideline, xdata=upperx, ydata=uppery) - self.canvas.draw() # Change value @@ -527,8 +504,6 @@ def move_upperSlider(self): self.ui.lineEdit_6.setText(str(newy)) self._upperSlideValue = inewy - return - def set_maxLogValue(self): """ Set maximum log value from line-edit """ @@ -570,7 +545,6 @@ def set_maxLogValue(self): upperx = self.ui.mainplot.get_xlim() uppery = [newmaxY, newmaxY] setp(self.upperslideline, xdata=upperx, ydata=uppery) - self.canvas.draw() # Set the value to upper slider @@ -581,8 +555,6 @@ def set_maxLogValue(self): if resetL is True: self.ui.lineEdit_6.setText(str(newmaxY)) - return - def browse_File(self): """ Open a file dialog to get file """ @@ -594,8 +566,6 @@ def browse_File(self): info_msg = "Selected file: %s." % str(filename) Logger("Filter_Events").information(info_msg) - return - def load_File(self): """ Load the file by file name or run number """ @@ -614,8 +584,6 @@ def load_File(self): # Reset GUI self._resetGUI(resetfilerun=False) - return - def use_existWS(self): """ Set up workspace to an existing one """ @@ -630,8 +598,6 @@ def use_existWS(self): # Reset GUI self._resetGUI(resetfilerun=True) - return - def plotLogValue(self): """ Plot log value """ @@ -689,7 +655,6 @@ def plotLogValue(self): self._upperSlideValue = 100 self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.lineEdit_6.setText("") - self.canvas.draw() # Load property's statistic and give suggestion on parallel and fast log @@ -797,8 +762,6 @@ def scanEventWorkspaces(self): self.ui.comboBox.clear() self.ui.comboBox.addItems(eventwsnames) - return - def _loadFile(self, filename): """ Load file or run File will be loaded to a workspace shown in MantidPlot @@ -917,11 +880,8 @@ def _plotTimeCounts(self, wksp): newrightx = xmin + (xmax-xmin)*self._rightSlideValue*0.01 setp(self.rightslideline, xdata=[newrightx, newrightx], ydata=newslidery) - self.canvas.draw() - return - def filterByTime(self): """ Filter by time """ @@ -953,8 +913,6 @@ def filterByTime(self): self.splitWksp(splitws, infows) - return - def filterByLogValue(self): """ Filter by log value """ @@ -1018,8 +976,6 @@ def filterByLogValue(self): except RuntimeError as e: self._setErrorMsg("Splitting Failed!\n %s" % (str(e))) - return - def splitWksp(self, splitws, infows): """ Run FilterEvents """ @@ -1057,8 +1013,6 @@ def splitWksp(self, splitws, infows): OutputWorkspaceIndexedFrom1=startfrom1, OutputTOFCorrectionWorkspace='TOFCorrTable', **kwargs) - return - def showHideEi(self): """ """ @@ -1086,8 +1040,6 @@ def showHideEi(self): self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() - return - def _searchTableWorkspaces(self): """ Search table workspaces and add to 'comboBox_corrWS' """ @@ -1104,8 +1056,6 @@ def _searchTableWorkspaces(self): if len(tablewsnames) > 0: self.ui.comboBox_corrWS.addItems(tablewsnames) - return - def _setErrorMsg(self, errmsg): """ Clear error message """ @@ -1150,7 +1100,6 @@ def _resetGUI(self, resetfilerun=False): xlim = self.ui.mainplot.get_xlim() setp(self.lowerslideline, xdata=xlim, ydata=[miny, miny]) setp(self.upperslideline, xdata=xlim, ydata=[maxy, maxy]) - self.canvas.draw() self.ui.lineEdit_7.clear() self.ui.lineEdit_8.clear() @@ -1173,7 +1122,4 @@ def _resetGUI(self, resetfilerun=False): self.ui.checkBox_groupWS.setCheckState(True) self.ui.checkBox_splitLog.setCheckState(False) - # Error message - # self.ui.plainTextEdit_ErrorMsg.clear() - - return + self.canvas.draw()