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

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

Refactored fitting options tab

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