source: sasview/src/sas/qtgui/Perspectives/Fitting/GPUOptions.py @ 740a738

ESS_GUI_bumps_abstraction
Last change on this file since 740a738 was 33c0561, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 5 years ago

Replace Apply button menu driven functionality with additional button.
Removed Cancel.
Removed the window system context help button from all affected widgets.
SASVIEW-1239

  • Property mode set to 100644
File size: 8.5 KB
RevLine 
[06ce180]1# global
[a6cd8d1]2import os
3import sys
[ced1bff]4import json
5import platform
[f1f3e6a]6import webbrowser
[8479735]7import logging
8
9import sasmodels
10import sasmodels.model_test
11import sasmodels.kernelcl
[06ce180]12
[9863343]13import sas.qtgui.Utilities.GuiUtils as GuiUtils
[e90988c]14from PyQt5 import QtGui, QtCore, QtWidgets
[06ce180]15from sas.qtgui.Perspectives.Fitting.UI.GPUOptionsUI import Ui_GPUOptions
[ced1bff]16from sas.qtgui.Perspectives.Fitting.UI.GPUTestResultsUI import Ui_GPUTestResults
[06ce180]17
[14fa542]18try:
19    _fromUtf8 = QtCore.QString.fromUtf8
20except AttributeError:
21    def _fromUtf8(s):
22        return s
[06ce180]23
[14fa542]24try:
[1543f0c]25    _encoding = QtWidgets.QApplication.UnicodeUTF8
[14fa542]26    def _translate(context, text, disambig):
[1543f0c]27        return QtWidgets.QApplication.translate(context, text, disambig, _encoding)
[14fa542]28except AttributeError:
29    def _translate(context, text, disambig):
[1543f0c]30        return QtWidgets.QApplication.translate(context, text, disambig)
[06ce180]31
[8479735]32logger = logging.getLogger(__name__)
[06ce180]33
[1543f0c]34class GPUOptions(QtWidgets.QDialog, Ui_GPUOptions):
[06ce180]35    """
[37be27f]36    OpenCL Dialog to select the desired OpenCL driver
[06ce180]37    """
38
[a6cd8d1]39    clicked = False
40    sas_open_cl = None
[db05c44]41    cl_options = None
[a6cd8d1]42
[06ce180]43    def __init__(self, parent=None):
44        super(GPUOptions, self).__init__(parent)
[a6cd8d1]45        self.parent = parent
[06ce180]46        self.setupUi(self)
[33c0561]47        # disable the context help icon
48        self.setWindowFlags(self.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint)
[a6cd8d1]49        self.addOpenCLOptions()
50        self.createLinks()
[06ce180]51
[a6cd8d1]52    def addOpenCLOptions(self):
53        """
54        Populate the window with a list of OpenCL options
55        """
[14fa542]56        # Get list of openCL options and add to GUI
[a6cd8d1]57        cl_tuple = _get_clinfo()
58        self.sas_open_cl = os.environ.get("SAS_OPENCL", "")
[db05c44]59
60        # Keys are the names in the form "platform: device". Corresponding values are the combined indices, e.g.
61        # "0:1", for setting the SAS_OPENCL env.
62        self.cl_options = {}
63
[14fa542]64        for title, descr in cl_tuple:
[c31d41e7]65            # Create an item for each openCL option
[1543f0c]66            check_box = QtWidgets.QCheckBox()
[37be27f]67            check_box.setObjectName(_fromUtf8(descr))
68            check_box.setText(_translate("GPUOptions", descr, None))
[c31d41e7]69            self.optionsLayout.addWidget(check_box)
[db05c44]70            if (title == self.sas_open_cl) or (
[37be27f]71                            title == "None" and not self.clicked):
72                check_box.click()
[a6cd8d1]73                self.clicked = True
[db05c44]74            self.cl_options[descr] = title
[1543f0c]75        self.openCLCheckBoxGroup.setMinimumWidth(self.optionsLayout.sizeHint().width()+10)
[37be27f]76
[a6cd8d1]77    def createLinks(self):
78        """
[37be27f]79        Link user interactions to function calls
[a6cd8d1]80        """
[9863343]81        self.testButton.clicked.connect(self.testButtonClicked)
82        self.helpButton.clicked.connect(self.helpButtonClicked)
[1543f0c]83        for item in self.openCLCheckBoxGroup.findChildren(QtWidgets.QCheckBox):
[9863343]84            item.clicked.connect(self.checked)
[a6cd8d1]85
86    def checked(self):
87        """
[37be27f]88        Only allow a single check box to be selected. Uncheck others.
[a6cd8d1]89        """
[1df1025]90        checked = None
[1543f0c]91        for box in self.openCLCheckBoxGroup.findChildren(QtWidgets.QCheckBox):
[db05c44]92            if box.isChecked() and (self.cl_options[str(box.text())] == self.sas_open_cl or (
[37be27f]93                    str(box.text()) == "No OpenCL" and self.sas_open_cl == "")):
[a6cd8d1]94                box.setChecked(False)
[37be27f]95            elif box.isChecked():
[1df1025]96                checked = box
97        if hasattr(checked, "text"):
[db05c44]98            self.sas_open_cl = self.cl_options[str(checked.text())]
[a6cd8d1]99        else:
100            self.sas_open_cl = None
101
[0bb1397]102    def set_sas_open_cl(self):
[ced1bff]103        """
[37be27f]104        Set SAS_OPENCL value when tests run or OK button clicked
[a6cd8d1]105        """
[ced1bff]106        no_opencl_msg = False
107        if self.sas_open_cl:
108            os.environ["SAS_OPENCL"] = self.sas_open_cl
109            if self.sas_open_cl.lower() == "none":
110                no_opencl_msg = True
111        else:
112            if "SAS_OPENCL" in os.environ:
113                del os.environ["SAS_OPENCL"]
114        # Sasmodels kernelcl doesn't exist when initiated with None
[8479735]115        sasmodels.kernelcl.reset_environment()
[ced1bff]116        return no_opencl_msg
117
118    def testButtonClicked(self):
[a6cd8d1]119        """
[ced1bff]120        Run sasmodels check from here and report results from
121        """
122
[0bb1397]123        no_opencl_msg = self.set_sas_open_cl()
[ced1bff]124
125        # Only import when tests are run
126        from sasmodels.model_test import model_tests
127
128        try:
[8479735]129            env = sasmodels.kernelcl.environment()
[ced1bff]130            clinfo = [(ctx.devices[0].platform.vendor,
131                       ctx.devices[0].platform.version,
132                       ctx.devices[0].vendor,
133                       ctx.devices[0].name,
134                       ctx.devices[0].version)
135                      for ctx in env.context]
[8479735]136        except Exception:
[ced1bff]137            clinfo = None
138
139        failures = []
140        tests_completed = 0
141        for test in model_tests():
142            try:
143                test()
144            except Exception:
145                failures.append(test.description)
146
147            tests_completed += 1
148
149        info = {
150            'version': sasmodels.__version__,
151            'platform': platform.uname(),
152            'opencl': clinfo,
153            'failing tests': failures,
154        }
155
156        msg = str(tests_completed) + ' tests completed.\n'
157        if len(failures) > 0:
158            msg += str(len(failures)) + ' tests failed.\n'
159            msg += 'Failing tests: '
160            msg += json.dumps(info['failing tests'])
161            msg += "\n"
162        else:
163            msg += "All tests passed!\n"
164
165        msg += "\nPlatform Details:\n\n"
166        msg += "Sasmodels version: "
167        msg += info['version'] + "\n"
168        msg += "\nPlatform used: "
169        msg += json.dumps(info['platform']) + "\n"
170        if no_opencl_msg:
171            msg += "\nOpenCL driver: None"
172        else:
173            msg += "\nOpenCL driver: "
174            msg += json.dumps(info['opencl']) + "\n"
[9863343]175        GPUTestResults(self, msg)
[a6cd8d1]176
177    def helpButtonClicked(self):
178        """
179        Open the help menu when the help button is clicked
180        """
[9863343]181        help_location = GuiUtils.HELP_DIRECTORY_LOCATION
[aed0532]182        help_location += "/user/qtgui/Perspectives/Fitting/gpu_setup.html"
[9863343]183        help_location += "#device-selection"
[e90988c]184        # Display the page in default browser
[f1f3e6a]185        webbrowser.open('file://' + os.path.realpath(help_location))
[a6cd8d1]186
187    def reject(self):
188        """
189        Close the window without modifying SAS_OPENCL
190        """
[c82fd8f]191        self.closeEvent(None)
192        self.parent.gpu_options_widget.open()
[a6cd8d1]193
194    def accept(self):
195        """
196        Close the window after modifying the SAS_OPENCL value
197        """
[0bb1397]198        self.set_sas_open_cl()
199        self.closeEvent(None)
[a6cd8d1]200
201    def closeEvent(self, event):
202        """
203        Overwrite QDialog close method to allow for custom widget close
204        """
[c82fd8f]205        self.close()
[0bb1397]206        self.parent.gpu_options_widget = GPUOptions(self.parent)
[a6cd8d1]207
208
[1543f0c]209class GPUTestResults(QtWidgets.QDialog, Ui_GPUTestResults):
[ced1bff]210    """
211    OpenCL Dialog to modify the OpenCL options
212    """
[9863343]213    def __init__(self, parent, msg):
[ced1bff]214        super(GPUTestResults, self).__init__(parent)
215        self.setupUi(self)
216        self.resultsText.setText(_translate("GPUTestResults", msg, None))
[1543f0c]217        #self.setFixedSize(self.size())
[ced1bff]218        self.open()
219
220
[a6cd8d1]221def _get_clinfo():
222    """
[37be27f]223    Read in information about available OpenCL infrastructure
[a6cd8d1]224    """
225    clinfo = []
[9863343]226    cl_platforms = []
[8479735]227
[a6cd8d1]228    try:
229        import pyopencl as cl
230    except ImportError:
[8479735]231        cl = None
232
233    if cl is None:
234        logger.warn("Unable to import the pyopencl package.  It may not "
235                    "have been installed.  If you wish to use OpenCL, try "
236                    "running pip install --user pyopencl")
237    else:
238        try:
239            cl_platforms = cl.get_platforms()
240        except cl.LogicError as err:
241            logger.warn("Unable to fetch the OpenCL platforms.  This likely "
242                        "means that the opencl drivers for your system are "
243                        "not installed.")
244            logger.warn(err)
[a6cd8d1]245
246    p_index = 0
[9863343]247    for cl_platform in cl_platforms:
[a6cd8d1]248        d_index = 0
[8a518285]249        cl_devices = cl_platform.get_devices()
250        for cl_device in cl_devices:
251            if len(cl_platforms) > 1 and len(cl_devices) > 1:
[a6cd8d1]252                combined_index = ":".join([str(p_index), str(d_index)])
[9863343]253            elif len(cl_platforms) > 1:
[a6cd8d1]254                combined_index = str(p_index)
255            else:
256                combined_index = str(d_index)
[8a518285]257            clinfo.append((combined_index, ": ".join([cl_platform.name,
258                                                     cl_device.name])))
[a6cd8d1]259            d_index += 1
260        p_index += 1
261
262    clinfo.append(("None", "No OpenCL"))
263    return clinfo
Note: See TracBrowser for help on using the repository browser.