source: sasview/src/sas/qtgui/Perspectives/Fitting/MultiConstraint.py @ e147ce2

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since e147ce2 was e147ce2, checked in by Piotr Rozyczko <rozyczko@…>, 6 years ago

Minor fixes after rebasing ESS_GUI branch

  • Property mode set to 100644
File size: 4.6 KB
Line 
1"""
2Widget for parameter constraints.
3"""
4import os
5from numpy import *
6
7from PyQt5 import QtCore
8from PyQt5 import QtGui
9from PyQt5 import QtWidgets
10import webbrowser
11
12import sas.qtgui.Utilities.GuiUtils as GuiUtils
13
14# Local UI
15from sas.qtgui.Perspectives.Fitting.UI.MultiConstraintUI import Ui_MultiConstraintUI
16
17class MultiConstraint(QtWidgets.QDialog, Ui_MultiConstraintUI):
18    def __init__(self, parent=None, params=None):
19        super(MultiConstraint, self).__init__()
20
21        self.setupUi(self)
22        self.setFixedSize(self.minimumSizeHint())
23        self.setModal(True)
24        self.params = params
25
26        self.setupLabels()
27        self.setupTooltip()
28
29        # Set param text control to the second parameter passed
30        self.txtConstraint.setText(self.params[1])
31
32        self.cmdOK.clicked.connect(self.accept)
33        self.cmdHelp.clicked.connect(self.onHelp)
34        self.cmdRevert.clicked.connect(self.revert)
35        self.txtConstraint.editingFinished.connect(self.validateFormula)
36
37    def revert(self):
38        """
39        switch M1 <-> M2
40        """
41        # Switch parameters
42        self.params[1], self.params[0] = self.params[0], self.params[1]
43        # Try to swap parameter names in the line edit
44        current_text = self.txtConstraint.text()
45        new_text = current_text.replace(self.params[0], self.params[1])
46        self.txtConstraint.setText(new_text)
47        # Update labels and tooltips
48        self.setupLabels()
49        self.setupTooltip()
50
51    def setupLabels(self):
52        """
53        Setup labels based on current parameters
54        """
55        l1 = self.params[0]
56        l2 = self.params[1]
57        self.txtParam1.setText(l1)
58        self.txtParam1_2.setText(l1)
59        self.txtParam2.setText(l2)
60
61    def setupTooltip(self):
62        """
63        Tooltip for txtConstraint
64        """
65        tooltip = "E.g.\n%s = 2.0 * (%s)\n" %(self.params[0], self.params[1])
66        tooltip += "%s = sqrt(%s) + 5"%(self.params[0], self.params[1])
67        self.txtConstraint.setToolTip(tooltip)
68
69    def validateFormula(self):
70        """
71        Add visual cues when formula is incorrect
72        """
73        formula_is_valid = False
74        formula_is_valid = self.validateConstraint(self.txtConstraint.text())
75        if not formula_is_valid:
76            self.cmdOK.setEnabled(False)
77            self.txtConstraint.setStyleSheet("QLineEdit {background-color: red;}")
78        else:
79            self.cmdOK.setEnabled(True)
80            self.txtConstraint.setStyleSheet("QLineEdit {background-color: white;}")
81
82    def validateConstraint(self, constraint_text):
83        """
84        Ensure the constraint has proper form
85        """
86        # 0. none or empty
87        if not constraint_text or not isinstance(constraint_text, str):
88            return False
89
90        param_str = str(self.params[1])
91        constraint_text = constraint_text.strip()
92
93        # 1. just the parameter
94        if param_str == constraint_text:
95            return True
96
97        # 2. ensure the text contains parameter name
98        parameter_string_start = constraint_text.find(param_str)
99        if parameter_string_start < 0:
100            return False
101        parameter_string_end = parameter_string_start + len(param_str)
102
103        # 3. parameter name should be a separate word, but can have "()[]*+-/ " around
104        valid_neighbours = "()[]*+-/ "
105        has_only_parameter = False
106        start_loc = parameter_string_start -1
107        end_loc = parameter_string_end
108        if not any([constraint_text[start_loc] == char for char in valid_neighbours]):
109            return False
110        if end_loc < len(constraint_text):
111            if not any([constraint_text[end_loc] == char for char in valid_neighbours]):
112                return False
113
114        # 4. replace parameter name with "1" and try to evaluate the expression
115        try:
116            expression_to_evaluate = constraint_text.replace(param_str, "1.0")
117            eval(expression_to_evaluate)
118        except Exception:
119            # Too many cases to cover individually, just a blanket
120            # Exception should be sufficient
121            # Note that in current numpy things like sqrt(-1) don't
122            # raise but just return warnings
123            return False
124
125        return True
126
127    def onHelp(self):
128        """
129        Display related help section
130        """
131        try:
132            help_location = GuiUtils.HELP_DIRECTORY_LOCATION + \
133            "/user/sasgui/perspectives/fitting/fitting_help.html#simultaneous-fits-with-constraints"
134            webbrowser.open('file://' + os.path.realpath(help_location))
135        except AttributeError:
136            # No manager defined - testing and standalone runs
137            pass
138
139
Note: See TracBrowser for help on using the repository browser.