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

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

Nearly done with data handling in P(r).

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