source: sasview/src/sas/qtgui/Perspectives/PrInversion/PrInversionPerspective.py @ 8045572

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 8045572 was 8045572, checked in by krzywon, 7 years ago

Laid ground work for batch P(r). P(r) GUI logic implemented, but not fully working.

  • Property mode set to 100644
File size: 11.9 KB
Line 
1import logging
2import numpy as np
3
4from PyQt4 import QtGui, QtCore, QtWebKit
5
6# sas-global
7import sas.qtgui.Utilities.GuiUtils as GuiUtils
8
9# pr inversion gui elements
10from PrInversionUtils import WIDGETS
11from UI.TabbedPrInversionUI import Ui_PrInversion
12
13class PrInversionWindow(QtGui.QTabWidget, Ui_PrInversion):
14    """
15    """
16
17    name = "PrInversion"
18
19    def __init__(self, parent=None, data=None):
20        super(PrInversionWindow, self).__init__()
21        self.setupUi(self)
22
23        self.setWindowTitle("P(r) Inversion Perspective")
24
25        self._manager = parent
26        self._model_item = QtGui.QStandardItem()
27        self._helpView = QtWebKit.QWebView()
28        self._data = data
29
30        # The tabs need to be closeable
31        self._allow_close = False
32
33        # Set initial values
34        self._data_index = 0
35        self._path = [""]
36        self._background = [0.0]
37        self._qmin = [0.0]
38        self._qmax = [1.0]
39        self._slit_height = [0.0]
40        self._slit_width = [0.0]
41        self._terms = [10]
42        self._regularization = [0.0001]
43        self._max_distance = [140]
44        self._bgd_input = [False]
45        self._terms_button = [False]
46        self._reg_button = [False]
47        self._terms_label = [""]
48        self._reg_label = [""]
49        # Set results
50        self._rg = [0.0]
51        self._i_0 = [0.0]
52        self._comp_time = [0.0]
53        self._chi_dof = [0.0]
54        self._oscillations = [0.0]
55        self._pos_fraction = [0.0]
56        self._sigma_pos_fraction = [0.0]
57
58        # Let's choose the Standard Item Model.
59        self.model = QtGui.QStandardItemModel(self)
60        # Set up the Widget Map
61        self.setupMapper()
62        # Set values
63        self.setupModel()
64        # Link user interactions with methods
65        self.setupLinks()
66
67        self.communicate = GuiUtils.Communicate()
68        logging.debug("P(r) Inversion Perspective loaded")
69
70    ######################################################################
71    # Base Perspective Class Definitions
72
73    def allowBatch(self):
74        return True
75
76    def setClosable(self, value=True):
77        """
78        Allow outsiders close this widget
79        """
80        assert isinstance(value, bool)
81        self._allow_close = value
82
83    def closeEvent(self, event):
84        """
85        Overwrite QDialog close method to allow for custom widget close
86        """
87        if self._allow_close:
88            # reset the closability flag
89            self.setClosable(value=False)
90            event.accept()
91        else:
92            event.ignore()
93            # Maybe we should just minimize
94            self.setWindowState(QtCore.Qt.WindowMinimized)
95
96    ######################################################################
97    # Initialization routines
98
99    def setupLinks(self):
100        self.dataList.currentIndexChanged.connect(self.displayChange)
101        self.calculateButton.clicked.connect(self.calculatePrInversion)
102        self.statusButton.clicked.connect(self.status)
103        self.helpButton.clicked.connect(self.help)
104        self.estimateBgd.toggled.connect(self.toggleBgd)
105        self.manualBgd.toggled.connect(self.toggleBgd)
106        self.explorerButton.clicked.connect(self.openExplorerWindow)
107        pass
108
109    def setupMapper(self):
110        # Set up the mapper.
111        self.mapper = QtGui.QDataWidgetMapper(self)
112        self.mapper.setOrientation(QtCore.Qt.Vertical)
113        self.mapper.setModel(self.model)
114
115        # Filename
116        self.mapper.addMapping(self.dataList, WIDGETS.W_FILENAME)
117        # Background
118        self.mapper.addMapping(self.backgroundInput, WIDGETS.W_BACKGROUND)
119        self.mapper.addMapping(self.estimateBgd, WIDGETS.W_ESTIMATE)
120        self.mapper.addMapping(self.manualBgd, WIDGETS.W_MANUAL_INPUT)
121
122        # Qmin/Qmax
123        self.mapper.addMapping(self.minQInput, WIDGETS.W_QMIN)
124        self.mapper.addMapping(self.maxQInput, WIDGETS.W_QMAX)
125
126        # Slit Parameter items
127        self.mapper.addMapping(self.slitWidthInput, WIDGETS.W_SLIT_WIDTH)
128        self.mapper.addMapping(self.slitHeightInput, WIDGETS.W_SLIT_HEIGHT)
129
130        # Parameter Items
131        self.mapper.addMapping(self.regularizationConstantInput,
132                               WIDGETS.W_REGULARIZATION)
133        self.mapper.addMapping(self.regConstantSuggestionButton,
134                               WIDGETS.W_REGULARIZATION_SUGGEST)
135        self.mapper.addMapping(self.explorerButton, WIDGETS.W_EXPLORE)
136        self.mapper.addMapping(self.maxDistanceInput, WIDGETS.W_MAX_DIST)
137        self.mapper.addMapping(self.noOfTermsInput, WIDGETS.W_NO_TERMS)
138        self.mapper.addMapping(self.noOfTermsSuggestionButton,
139                               WIDGETS.W_NO_TERMS_SUGGEST)
140
141        # Output
142        self.mapper.addMapping(self.rgValue, WIDGETS.W_RG)
143        self.mapper.addMapping(self.iQ0Value, WIDGETS.W_I_ZERO)
144        self.mapper.addMapping(self.backgroundValue, WIDGETS.W_BACKGROUND)
145        self.mapper.addMapping(self.computationTimeValue, WIDGETS.W_COMP_TIME)
146        self.mapper.addMapping(self.chiDofValue, WIDGETS.W_CHI_SQUARED)
147        self.mapper.addMapping(self.oscillationValue, WIDGETS.W_OSCILLATION)
148        self.mapper.addMapping(self.posFractionValue, WIDGETS.W_POS_FRACTION)
149        self.mapper.addMapping(self.sigmaPosFractionValue,
150                               WIDGETS.W_SIGMA_POS_FRACTION)
151
152        # Main Buttons
153        self.mapper.addMapping(self.calculateButton, WIDGETS.W_CALCULATE)
154        self.mapper.addMapping(self.statusButton, WIDGETS.W_STATUS)
155        self.mapper.addMapping(self.helpButton, WIDGETS.W_HELP)
156
157        self.mapper.toFirst()
158
159    ######################################################################
160    # Methods for updating GUI
161
162    def setupModel(self):
163        """
164        Update boxes with latest values
165        """
166        item = QtGui.QStandardItem(self._path[self._data_index])
167        self.model.setItem(WIDGETS.W_FILENAME, item)
168        item = QtGui.QStandardItem(self._background[self._data_index])
169        self.model.setItem(WIDGETS.W_BACKGROUND, item)
170        self.checkBgdClicked(self._bgd_input[self._data_index])
171        item = QtGui.QStandardItem(self._qmin[self._data_index])
172        self.model.setItem(WIDGETS.W_QMIN, item)
173        item = QtGui.QStandardItem(self._qmax[self._data_index])
174        self.model.setItem(WIDGETS.W_QMAX, item)
175        item = QtGui.QStandardItem(self._slit_width[self._data_index])
176        self.model.setItem(WIDGETS.W_SLIT_WIDTH, item)
177        item = QtGui.QStandardItem(self._slit_height[self._data_index])
178        self.model.setItem(WIDGETS.W_SLIT_HEIGHT, item)
179        item = QtGui.QStandardItem(self._terms[self._data_index])
180        self.model.setItem(WIDGETS.W_NO_TERMS, item)
181        item = QtGui.QStandardItem(self._regularization[self._data_index])
182        self.model.setItem(WIDGETS.W_REGULARIZATION, item)
183        item = QtGui.QStandardItem(self._max_distance[self._data_index])
184        self.model.setItem(WIDGETS.W_MAX_DIST, item)
185        item = QtGui.QStandardItem(self._rg[self._data_index])
186        self.model.setItem(WIDGETS.W_RG, item)
187        item = QtGui.QStandardItem(self._i_0[self._data_index])
188        self.model.setItem(WIDGETS.W_I_ZERO, item)
189        item = QtGui.QStandardItem(self._background[self._data_index])
190        self.model.setItem(WIDGETS.W_BACKGROUND, item)
191        item = QtGui.QStandardItem(self._comp_time[self._data_index])
192        self.model.setItem(WIDGETS.W_COMP_TIME, item)
193        item = QtGui.QStandardItem(self._chi_dof[self._data_index])
194        self.model.setItem(WIDGETS.W_CHI_SQUARED, item)
195        item = QtGui.QStandardItem(self._oscillations[self._data_index])
196        self.model.setItem(WIDGETS.W_OSCILLATION, item)
197        item = QtGui.QStandardItem(self._pos_fraction[self._data_index])
198        self.model.setItem(WIDGETS.W_POS_FRACTION, item)
199        item = QtGui.QStandardItem(self._sigma_pos_fraction[self._data_index])
200        self.model.setItem(WIDGETS.W_SIGMA_POS_FRACTION, item)
201        self.enableButtons()
202
203    def enableButtons(self):
204        """
205        Disable buttons when no data present, else enable them
206        """
207        if self._path[self._data_index] == "" and len(self._path) == 1:
208            self.calculateButton.setEnabled(False)
209            self.explorerButton.setEnabled(False)
210            self.statusButton.setEnabled(False)
211        else:
212            self.statusButton.setEnabled(True)
213            self.explorerButton.setEnabled(True)
214            self.calculateButton.setEnabled(True)
215
216    def reDraw(self):
217        """
218        Redraws the window with any and all necessary updates.
219        """
220        self.populateDataComboBox()
221        self.dataList.setCurrentIndex(self._data_index)
222        self.setupModel()
223
224    def populateDataComboBox(self):
225        string_list = QtCore.QStringList()
226        for item in self._data:
227            qt_item = QtCore.QString.fromUtf8(item)
228            string_list.append(qt_item)
229        self.dataList.addItems(string_list)
230
231    def _addPr(self, data_list):
232        """
233        Add a new data set to the P(r) window and updates as needed.
234        :param data_list: List of data sent from the data manager
235        """
236        assert data_list is not None
237
238        for data in data_list:
239            # TODO: populate class variable lists with data from data_list
240            pass
241        self.reDraw()
242
243
244    ######################################################################
245    # GUI Actions
246
247    def calculatePrInversion(self):
248        """
249        Calculate the P(r) for every data set in the data list
250        """
251        pass
252
253    def status(self):
254        """
255        Show the status of the calculations
256        """
257        pass
258
259    def help(self):
260        """
261        Open the P(r) Inversion help browser
262        """
263        tree_location = (GuiUtils.HELP_DIRECTORY_LOCATION +
264                         "user/sasgui/perspectives/pr/pr_help.html")
265
266        # Actual file anchor will depend on the combo box index
267        # Note that we can be clusmy here, since bad current_fitter_id
268        # will just make the page displayed from the top
269        self._helpView.load(QtCore.QUrl(tree_location))
270        self._helpView.show()
271
272    def checkBgdClicked(self, boolean=None):
273        if boolean or self.manualBgd.isChecked():
274            self.manualBgd.setChecked(True)
275            self.toggleBgd(self.manualBgd)
276            self._bgd_input[self._data_index] = True
277        else:
278            self.estimateBgd.setChecked(True)
279            self.toggleBgd(self.estimateBgd)
280            self._bgd_input[self._data_index] = False
281
282    def toggleBgd(self, item=None):
283        """
284        Toggle the background between manual and estimated
285        :param item: gui item that was triggered
286        """
287        if not item:
288            self.checkBgdClicked()
289        elif isinstance(item, QtGui.QRadioButton):
290            if item is self.estimateBgd:
291                self.backgroundInput.setEnabled(False)
292            else:
293                self.backgroundInput.setEnabled(True)
294
295    def openExplorerWindow(self):
296        """
297        Open the Explorer window to see correlations between params and results
298        """
299        # TODO: This depends on SVCC-45
300        pass
301
302    def displayChange(self):
303        """
304        Display the values of the data set selected from the data combo box
305        """
306        self._data_index = self.dataList.currentIndex()
307        self.setupModel()
308
309    ######################################################################
310    # Response Actions
311
312    def setData(self, data_item=None, is_batch=False):
313        """
314        Assign new data set or sets to the P(r) perspective
315        Obtain a QStandardItem object and dissect it to get Data1D/2D
316        Pass it over to the calculator
317        """
318        assert data_item is not None
319
320        if not isinstance(data_item, list):
321            msg = "Incorrect type passed to the P(r) Perspective"
322            raise AttributeError, msg
323
324        if not isinstance(data_item[0], QtGui.QStandardItem):
325            msg = "Incorrect type passed to the P(r) Perspective"
326            raise AttributeError, msg
327
328        self._addPr(data_item)
Note: See TracBrowser for help on using the repository browser.