source: sasview/src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py @ d76beb4

ESS_GUI
Last change on this file since d76beb4 was d76beb4, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 8 months ago

Unify default qmin/qmax/npts. SASVIEW-1294

  • Property mode set to 100644
File size: 7.1 KB
Line 
1"""
2Widget/logic for smearing data.
3"""
4import numpy as np
5from PyQt5 import QtCore
6from PyQt5 import QtGui
7from PyQt5 import QtWidgets
8
9from sas.qtgui.Plotting.PlotterData import Data2D
10import sas.qtgui.Utilities.GuiUtils as GuiUtils
11
12# Local UI
13from sas.qtgui.Perspectives.Fitting.UI.OptionsWidgetUI import Ui_tabOptions
14
15class DataWidgetMapper(QtWidgets.QDataWidgetMapper):
16    """
17    Custom version of the standard QDataWidgetMapper allowing for proper
18    response to index change in comboboxes
19    """
20    def addMapping(self, widget, section, propertyName=None):
21        if propertyName is None:
22            super(DataWidgetMapper, self).addMapping(widget, section)
23        else:
24            super(DataWidgetMapper, self).addMapping(widget, section, propertyName)
25
26        if isinstance(widget, QtWidgets.QComboBox):
27            delegate = self.itemDelegate()
28            widget.currentIndexChanged.connect(lambda: delegate.commitData.emit(widget))
29
30        elif isinstance(widget, QtWidgets.QCheckBox):
31            delegate = self.itemDelegate()
32            widget.stateChanged.connect(lambda: delegate.commitData.emit(widget))
33
34class OptionsWidget(QtWidgets.QWidget, Ui_tabOptions):
35    plot_signal = QtCore.pyqtSignal()
36    QMIN_DEFAULT = 0.0005
37    QMAX_DEFAULT = 0.5
38    NPTS_DEFAULT = 50
39    MODEL = [
40        'MIN_RANGE',
41        'MAX_RANGE',
42        'NPTS',
43        'LOG_SPACED']
44
45    def __init__(self, parent=None, logic=None):
46        super(OptionsWidget, self).__init__()
47
48        self.setupUi(self)
49
50        # Logic component
51        self.logic = logic
52        self.parent = parent
53
54        # Weight radio box group
55        self.weightingGroup = QtWidgets.QButtonGroup()
56        self.weighting = 0
57
58        # Group boxes
59        self.boxWeighting.setEnabled(False)
60        self.cmdMaskEdit.setEnabled(False)
61        # Button groups
62        self.weightingGroup.addButton(self.rbWeighting1)
63        self.weightingGroup.addButton(self.rbWeighting2)
64        self.weightingGroup.addButton(self.rbWeighting3)
65        self.weightingGroup.addButton(self.rbWeighting4)
66
67        # Let only floats in the range edits
68        self.txtMinRange.setValidator(GuiUtils.DoubleValidator())
69        self.txtMaxRange.setValidator(GuiUtils.DoubleValidator())
70        # Let only ints in the number of points edit
71        self.txtNpts.setValidator(QtGui.QIntValidator())
72
73        # Attach slots
74        self.cmdReset.clicked.connect(self.onRangeReset)
75        self.cmdMaskEdit.clicked.connect(self.onMaskEdit)
76        self.chkLogData.stateChanged.connect(self.toggleLogData)
77        # Button groups
78        self.weightingGroup.buttonClicked.connect(self.onWeightingChoice)
79
80        self.qmin = self.QMIN_DEFAULT
81        self.qmax = self.QMAX_DEFAULT
82        self.npts = self.NPTS_DEFAULT
83        if self.logic.data_is_loaded:
84            self.qmin, self.qmax, self.npts = self.logic.computeDataRange()
85        self.initModel()
86        self.initMapper()
87        self.model.blockSignals(True)
88        self.updateQRange(self.qmin, self.qmax, self.npts)
89        self.txtMaxRange.setText(GuiUtils.formatNumber(self.qmax, high=True))
90        self.txtMinRange.setText(GuiUtils.formatNumber(self.qmin, high=True))
91        self.txtNpts.setText(str(self.npts))
92        self.txtNptsFit.setText(str(self.npts))
93        self.model.blockSignals(False)
94
95        new_font = 'font-family: -apple-system, "Helvetica Neue", "Ubuntu";'
96        self.label_13.setStyleSheet(new_font)
97        self.label_15.setStyleSheet(new_font)
98
99    def initModel(self):
100        """
101        Initialize the state
102        """
103        self.model = QtGui.QStandardItemModel()
104        for model_item in range(len(self.MODEL)):
105            self.model.setItem(model_item, QtGui.QStandardItem())
106        # Attach slot
107        self.model.dataChanged.connect(self.onModelChange)
108
109    def initMapper(self):
110        """
111        Initialize model item <-> UI element mapping
112        """
113        self.mapper = DataWidgetMapper(self)
114
115        self.mapper.setModel(self.model)
116        self.mapper.setOrientation(QtCore.Qt.Vertical)
117
118        self.mapper.addMapping(self.txtMinRange, self.MODEL.index('MIN_RANGE'))
119        self.mapper.addMapping(self.txtMaxRange, self.MODEL.index('MAX_RANGE'))
120        self.mapper.addMapping(self.txtNpts,     self.MODEL.index('NPTS'))
121        self.mapper.addMapping(self.chkLogData,  self.MODEL.index('LOG_SPACED'))
122
123        self.mapper.toFirst()
124
125    def toggleLogData(self, isChecked):
126        """ Toggles between log and linear data sets """
127        pass
128
129    def onMaskEdit(self):
130        """
131        Callback for running the mask editor
132        """
133        if isinstance(self.logic.data, Data2D):
134            self.parent.communicate.maskEditorSignal.emit(self.logic.data)
135
136    def onRangeReset(self):
137        """
138        Callback for resetting qmin/qmax
139        """
140        self.updateQRange(self.qmin, self.qmax, self.npts)
141
142    def onWeightingChoice(self, button):
143        """
144        Update weighting in the fit state
145        """
146        button_id = button.group().checkedId()
147        self.weighting = abs(button_id + 2)
148        self.plot_signal.emit()
149
150    def onModelChange(self, top, bottom):
151        """
152        Respond to model change by updating the plot
153        """
154        # "bottom" is unused
155        # update if there's something to update
156        if str(self.model.item(top.row()).text()):
157            self.plot_signal.emit()
158
159    def setEnablementOnDataLoad(self):
160        """
161        Enable/disable various UI elements based on data loaded
162        """
163        is2Ddata = isinstance(self.logic.data, Data2D)
164        self.boxWeighting.setEnabled(True)
165        self.cmdMaskEdit.setEnabled(is2Ddata)
166        # Switch off txtNpts related controls
167        self.txtNpts.setEnabled(False)
168        self.txtNptsFit.setEnabled(False)
169        self.chkLogData.setEnabled(False)
170        # Weighting controls
171        if self.logic.di_flag:
172            self.rbWeighting2.setEnabled(True)
173            self.rbWeighting2.setChecked(True)
174            self.onWeightingChoice(self.rbWeighting2)
175        else:
176            self.rbWeighting2.setEnabled(False)
177            self.rbWeighting1.setChecked(True)
178            self.onWeightingChoice(self.rbWeighting1)
179
180    def updateQRange(self, q_range_min, q_range_max, npts):
181        """
182        Update the local model based on calculated values
183        """
184        qmax = GuiUtils.formatNumber(self.qmax, high=True)
185        qmin = GuiUtils.formatNumber(self.qmin, high=True)
186        self.model.item(self.MODEL.index('MIN_RANGE')).setText(qmin)
187        self.model.item(self.MODEL.index('MAX_RANGE')).setText(qmax)
188        self.model.item(self.MODEL.index('NPTS')).setText(str(npts))
189        self.qmin, self.qmax, self.npts = q_range_min, q_range_max, npts
190
191    def state(self):
192        """
193        Returns current state of controls
194        """
195        q_range_min = float(self.model.item(self.MODEL.index('MIN_RANGE')).text())
196        q_range_max = float(self.model.item(self.MODEL.index('MAX_RANGE')).text())
197        npts = int(self.model.item(self.MODEL.index('NPTS')).text())
198        log_points = str(self.model.item(self.MODEL.index('LOG_SPACED')).text()) == 'true'
199
200        return (q_range_min, q_range_max, npts, log_points, self.weighting)
Note: See TracBrowser for help on using the repository browser.