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

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 2109350 was 2109350, checked in by Piotr Rozyczko <rozyczko@…>, 6 years ago

More functionality for single model constraints SASVIEW-843

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