source: sasview/src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py @ 4cac8a47

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 4cac8a47 was 570a2f73, checked in by krzywon, 7 years ago

Track P(r) plots so they can be updated rather than replaced.

  • Property mode set to 100644
File size: 22.4 KB
RevLine 
[dab3351]1import sys
2import logging
[d1a4793]3import pylab
[8045572]4import numpy as np
[e32b120]5
[d2d0441e]6from PyQt4 import QtGui, QtCore, QtWebKit
[e7651ff]7from twisted.internet import reactor
[6cbf8a5]8
9# sas-global
[e32b120]10import sas.qtgui.Utilities.GuiUtils as GuiUtils
[6cbf8a5]11
[e7651ff]12# pr inversion GUI elements
13from InversionUtils import WIDGETS
[57ad773]14import UI.TabbedInversionUI
15from UI.TabbedInversionUI import Ui_PrInversion
[e7651ff]16from InversionLogic import InversionLogic
[6cbf8a5]17
[bde1a6b]18# pr inversion calculation elements
[d1a4793]19from sas.sascalc.dataloader.data_info import Data1D
[bde1a6b]20from sas.sascalc.pr.invertor import Invertor
21
[d1a4793]22def is_float(value):
[570a2f73]23    """Converts text input values to floats. Empty strings throw ValueError"""
[d1a4793]24    try:
25        return float(value)
26    except ValueError:
27        return 0.0
[bde1a6b]28
[570a2f73]29
30# TODO: Remove data
31# TODO: Modify plot references, don't just send new
32# TODO: Explorer button - link to PR from AW
33# TODO: Update help with batch capabilities
34# TODO: Window should not be fixed size
35# TODO: Easy way to scroll through results - no tabs in window(?) - 'spreadsheet'
36# TODO: Method to export results in some meaningful way
[e7651ff]37class InversionWindow(QtGui.QTabWidget, Ui_PrInversion):
[6cbf8a5]38    """
[406f420]39    The main window for the P(r) Inversion perspective.
[6cbf8a5]40    """
41
[e7651ff]42    name = "Inversion"
[6cbf8a5]43
44    def __init__(self, parent=None, data=None):
[e7651ff]45        super(InversionWindow, self).__init__()
[6cbf8a5]46        self.setupUi(self)
47
48        self.setWindowTitle("P(r) Inversion Perspective")
49
[d2d0441e]50        self._manager = parent
51        self._model_item = QtGui.QStandardItem()
52        self._helpView = QtWebKit.QWebView()
[406f420]53
[bde1a6b]54        self.communicate = GuiUtils.Communicate()
[6cbf8a5]55
[e7651ff]56        self.logic = InversionLogic()
57
[bde1a6b]58        # The window should not close
[6cbf8a5]59        self._allow_close = False
60
[e7651ff]61        # current QStandardItem showing on the panel
62        self._data = None
63        # current Data1D as referenced by self._data
64        self._data_set = None
[d1a4793]65
66        # p(r) calculator
67        self._calculator = Invertor()
68        self._last_calculator = None
69        self.calc_thread = None
70        self.estimation_thread = None
[bde1a6b]71
72        # Current data object in view
[8045572]73        self._data_index = 0
[bde1a6b]74        # list mapping data to p(r) calculation
[d132f33]75        self._data_list = {}
[bde1a6b]76        if not isinstance(data, list):
[d132f33]77            data_list = [data]
78        if data is not None:
79            for datum in data_list:
80                self._data_list[datum] = self._calculator.clone()
[bde1a6b]81
[570a2f73]82        # plots for current data
[e7651ff]83        self.pr_plot = None
84        self.data_plot = None
[570a2f73]85        # plot references for all data in perspective
86        self.pr_plot_list = {}
87        self.data_plot_list = {}
[e7651ff]88
[d2d0441e]89        self.model = QtGui.QStandardItemModel(self)
[bde1a6b]90        self.mapper = QtGui.QDataWidgetMapper(self)
[e32b120]91        # Link user interactions with methods
92        self.setupLinks()
[bde1a6b]93        # Set values
94        self.setupModel()
95        # Set up the Widget Map
96        self.setupMapper()
[c00a28ff]97        # Set base window state
98        self.setupWindow()
[d2d0441e]99
[8045572]100    ######################################################################
101    # Base Perspective Class Definitions
102
[e7651ff]103    def communicator(self):
104        return self.communicate
105
[d2d0441e]106    def allowBatch(self):
[d132f33]107        return True
[d2d0441e]108
109    def setClosable(self, value=True):
110        """
111        Allow outsiders close this widget
112        """
113        assert isinstance(value, bool)
114        self._allow_close = value
115
116    def closeEvent(self, event):
117        """
118        Overwrite QDialog close method to allow for custom widget close
119        """
120        if self._allow_close:
121            # reset the closability flag
122            self.setClosable(value=False)
123            event.accept()
124        else:
125            event.ignore()
126            # Maybe we should just minimize
127            self.setWindowState(QtCore.Qt.WindowMinimized)
[e32b120]128
[8045572]129    ######################################################################
130    # Initialization routines
131
[e32b120]132    def setupLinks(self):
[bde1a6b]133        """Connect the use controls to their appropriate methods"""
[d132f33]134        self.dataList.currentIndexChanged.connect(self.displayChange)
[c00a28ff]135        self.calculateAllButton.clicked.connect(self.startThreadAll)
136        self.calculateThisButton.clicked.connect(self.startThread)
[e32b120]137        self.helpButton.clicked.connect(self.help)
138        self.estimateBgd.toggled.connect(self.toggleBgd)
139        self.manualBgd.toggled.connect(self.toggleBgd)
[dab3351]140        self.regConstantSuggestionButton.clicked.connect(self.acceptAlpha)
141        self.noOfTermsSuggestionButton.clicked.connect(self.acceptNoTerms)
[e32b120]142        self.explorerButton.clicked.connect(self.openExplorerWindow)
[57ad773]143        self.backgroundInput.textChanged.connect(
144            lambda: self._calculator.set_est_bck(int(is_float(
145                str(self.backgroundInput.text())))))
146        self.minQInput.textChanged.connect(
147            lambda: self._calculator.set_qmin(is_float(
148                str(self.minQInput.text()))))
149        self.regularizationConstantInput.textChanged.connect(
150            lambda: self._calculator.set_alpha(is_float(
151                str(self.regularizationConstantInput.text()))))
152        self.maxDistanceInput.textChanged.connect(
153            lambda: self._calculator.set_dmax(is_float(
154                str(self.maxDistanceInput.text()))))
155        self.maxQInput.textChanged.connect(
156            lambda: self._calculator.set_qmax(is_float(
157                str(self.maxQInput.text()))))
158        self.slitHeightInput.textChanged.connect(
159            lambda: self._calculator.set_slit_height(is_float(
160                str(self.slitHeightInput.text()))))
161        self.slitWidthInput.textChanged.connect(
162            lambda: self._calculator.set_slit_width(is_float(
163                str(self.slitHeightInput.text()))))
[bde1a6b]164        self.model.itemChanged.connect(self.model_changed)
[e32b120]165
166    def setupMapper(self):
167        # Set up the mapper.
168        self.mapper.setOrientation(QtCore.Qt.Vertical)
169        self.mapper.setModel(self.model)
170
171        # Filename
[8045572]172        self.mapper.addMapping(self.dataList, WIDGETS.W_FILENAME)
[e32b120]173        # Background
[bde1a6b]174        self.mapper.addMapping(self.backgroundInput, WIDGETS.W_BACKGROUND_INPUT)
[e32b120]175        self.mapper.addMapping(self.estimateBgd, WIDGETS.W_ESTIMATE)
176        self.mapper.addMapping(self.manualBgd, WIDGETS.W_MANUAL_INPUT)
177
178        # Qmin/Qmax
179        self.mapper.addMapping(self.minQInput, WIDGETS.W_QMIN)
180        self.mapper.addMapping(self.maxQInput, WIDGETS.W_QMAX)
181
182        # Slit Parameter items
183        self.mapper.addMapping(self.slitWidthInput, WIDGETS.W_SLIT_WIDTH)
184        self.mapper.addMapping(self.slitHeightInput, WIDGETS.W_SLIT_HEIGHT)
185
186        # Parameter Items
[8045572]187        self.mapper.addMapping(self.regularizationConstantInput,
188                               WIDGETS.W_REGULARIZATION)
189        self.mapper.addMapping(self.regConstantSuggestionButton,
190                               WIDGETS.W_REGULARIZATION_SUGGEST)
[e32b120]191        self.mapper.addMapping(self.explorerButton, WIDGETS.W_EXPLORE)
192        self.mapper.addMapping(self.maxDistanceInput, WIDGETS.W_MAX_DIST)
193        self.mapper.addMapping(self.noOfTermsInput, WIDGETS.W_NO_TERMS)
[8045572]194        self.mapper.addMapping(self.noOfTermsSuggestionButton,
195                               WIDGETS.W_NO_TERMS_SUGGEST)
[e32b120]196
197        # Output
198        self.mapper.addMapping(self.rgValue, WIDGETS.W_RG)
199        self.mapper.addMapping(self.iQ0Value, WIDGETS.W_I_ZERO)
[bde1a6b]200        self.mapper.addMapping(self.backgroundValue, WIDGETS.W_BACKGROUND_OUTPUT)
[e32b120]201        self.mapper.addMapping(self.computationTimeValue, WIDGETS.W_COMP_TIME)
202        self.mapper.addMapping(self.chiDofValue, WIDGETS.W_CHI_SQUARED)
203        self.mapper.addMapping(self.oscillationValue, WIDGETS.W_OSCILLATION)
204        self.mapper.addMapping(self.posFractionValue, WIDGETS.W_POS_FRACTION)
[8045572]205        self.mapper.addMapping(self.sigmaPosFractionValue,
206                               WIDGETS.W_SIGMA_POS_FRACTION)
[e32b120]207
208        # Main Buttons
[c00a28ff]209        self.mapper.addMapping(self.calculateAllButton, WIDGETS.W_CALCULATE_ALL)
210        self.mapper.addMapping(self.calculateThisButton,
211                               WIDGETS.W_CALCULATE_VISIBLE)
[e32b120]212        self.mapper.addMapping(self.helpButton, WIDGETS.W_HELP)
213
214        self.mapper.toFirst()
215
216    def setupModel(self):
217        """
[bde1a6b]218        Update boxes with initial values
[e32b120]219        """
[bde1a6b]220        item = QtGui.QStandardItem("")
[e32b120]221        self.model.setItem(WIDGETS.W_FILENAME, item)
[bde1a6b]222        item = QtGui.QStandardItem('0.0')
223        self.model.setItem(WIDGETS.W_BACKGROUND_INPUT, item)
224        item = QtGui.QStandardItem("")
[e32b120]225        self.model.setItem(WIDGETS.W_QMIN, item)
[bde1a6b]226        item = QtGui.QStandardItem("")
[e32b120]227        self.model.setItem(WIDGETS.W_QMAX, item)
[bde1a6b]228        item = QtGui.QStandardItem("")
[e32b120]229        self.model.setItem(WIDGETS.W_SLIT_WIDTH, item)
[bde1a6b]230        item = QtGui.QStandardItem("")
[e32b120]231        self.model.setItem(WIDGETS.W_SLIT_HEIGHT, item)
[bde1a6b]232        item = QtGui.QStandardItem("10")
[e32b120]233        self.model.setItem(WIDGETS.W_NO_TERMS, item)
[bde1a6b]234        item = QtGui.QStandardItem("0.0001")
[e32b120]235        self.model.setItem(WIDGETS.W_REGULARIZATION, item)
[bde1a6b]236        item = QtGui.QStandardItem("140.0")
[e32b120]237        self.model.setItem(WIDGETS.W_MAX_DIST, item)
[bde1a6b]238        item = QtGui.QStandardItem("")
[e32b120]239        self.model.setItem(WIDGETS.W_RG, item)
[bde1a6b]240        item = QtGui.QStandardItem("")
[e32b120]241        self.model.setItem(WIDGETS.W_I_ZERO, item)
[bde1a6b]242        item = QtGui.QStandardItem("")
243        self.model.setItem(WIDGETS.W_BACKGROUND_OUTPUT, item)
244        item = QtGui.QStandardItem("")
[e32b120]245        self.model.setItem(WIDGETS.W_COMP_TIME, item)
[bde1a6b]246        item = QtGui.QStandardItem("")
[e32b120]247        self.model.setItem(WIDGETS.W_CHI_SQUARED, item)
[bde1a6b]248        item = QtGui.QStandardItem("")
[e32b120]249        self.model.setItem(WIDGETS.W_OSCILLATION, item)
[bde1a6b]250        item = QtGui.QStandardItem("")
[e32b120]251        self.model.setItem(WIDGETS.W_POS_FRACTION, item)
[bde1a6b]252        item = QtGui.QStandardItem("")
[e32b120]253        self.model.setItem(WIDGETS.W_SIGMA_POS_FRACTION, item)
[bde1a6b]254
[c00a28ff]255    def setupWindow(self):
256        """Initialize base window state on init"""
257        self.setTabPosition(0)
258        self.enableButtons()
259        self.estimateBgd.setChecked(True)
260
[bde1a6b]261    ######################################################################
262    # Methods for updating GUI
[8045572]263
264    def enableButtons(self):
265        """
[bde1a6b]266        Enable buttons when data is present, else disable them
[8045572]267        """
[c00a28ff]268        self.explorerButton.setEnabled(self.logic.data_is_loaded)
269        self.calculateAllButton.setEnabled(self.logic.data_is_loaded)
270        self.calculateThisButton.setEnabled(self.logic.data_is_loaded)
[8045572]271
[26f42b1]272    def populateDataComboBox(self, filename, data_ref):
[8045572]273        """
[bde1a6b]274        Append a new file name to the data combobox
275        :param data: Data1D object
[8045572]276        """
[bde1a6b]277        qt_item = QtCore.QString.fromUtf8(filename)
[26f42b1]278        ref = QtCore.QVariant(data_ref)
279        self.dataList.addItem(qt_item, ref)
[8045572]280
[dab3351]281    def acceptNoTerms(self):
282        """Send estimated no of terms to input"""
283        self.model.setItem(WIDGETS.W_NO_TERMS, QtGui.QStandardItem(
284            self.noOfTermsSuggestionButton.text()))
285
286    def acceptAlpha(self):
287        """Send estimated alpha to input"""
288        self.model.setItem(WIDGETS.W_REGULARIZATION, QtGui.QStandardItem(
289            self.regConstantSuggestionButton.text()))
290
[d132f33]291    def displayChange(self):
[dfd8233]292        variant_ref = self.dataList.itemData(self.dataList.currentIndex())
293        self.setCurrentData(variant_ref.toPyObject())
[d132f33]294
[8045572]295    ######################################################################
[dab3351]296    # GUI Interaction Events
[8045572]297
[d1a4793]298    def update_calculator(self):
[57ad773]299        """Update all p(r) params"""
[e7651ff]300        self._calculator.set_x(self._data_set.x)
301        self._calculator.set_y(self._data_set.y)
302        self._calculator.set_err(self._data_set.dy)
[d1a4793]303
[bde1a6b]304    def model_changed(self):
305        """Update the values when user makes changes"""
306        if not self.mapper:
[c00a28ff]307            msg = "Unable to update P{r}. The connection between the main GUI "
308            msg += "and P(r) was severed. Attempting to restart P(r)."
309            logging.warning(msg)
310            self.setClosable(True)
311            self.close()
312            InversionWindow.__init__(self.parent(), self._data_list.keys())
[570a2f73]313            exit(0)
314        # TODO: Only send plot first time - otherwise, update in complete
[57ad773]315        if self.pr_plot is not None:
316            title = self.pr_plot.name
317            GuiUtils.updateModelItemWithPlot(
318                self._data, QtCore.QVariant(self.pr_plot), title)
319        if self.data_plot is not None:
320            title = self.data_plot.name
321            GuiUtils.updateModelItemWithPlot(
322                self._data, QtCore.QVariant(self.data_plot), title)
[bde1a6b]323        self.mapper.toFirst()
324
[e32b120]325    def help(self):
[8045572]326        """
327        Open the P(r) Inversion help browser
328        """
329        tree_location = (GuiUtils.HELP_DIRECTORY_LOCATION +
330                         "user/sasgui/perspectives/pr/pr_help.html")
[e32b120]331
[8045572]332        # Actual file anchor will depend on the combo box index
333        # Note that we can be clusmy here, since bad current_fitter_id
334        # will just make the page displayed from the top
335        self._helpView.load(QtCore.QUrl(tree_location))
336        self._helpView.show()
337
[57ad773]338    def toggleBgd(self):
[8045572]339        """
340        Toggle the background between manual and estimated
341        """
[57ad773]342        sender = self.sender()
343        if sender is self.estimateBgd:
344            self.backgroundInput.setEnabled(False)
345        else:
346            self.backgroundInput.setEnabled(True)
[e32b120]347
348    def openExplorerWindow(self):
[8045572]349        """
350        Open the Explorer window to see correlations between params and results
351        """
[c00a28ff]352        # TODO: Look at PR from AW - Is there anything else I need to do?
[e32b120]353        pass
[8045572]354
355    ######################################################################
356    # Response Actions
357
358    def setData(self, data_item=None, is_batch=False):
359        """
[c00a28ff]360        Assign new data set(s) to the P(r) perspective
361        Obtain a QStandardItem object and parse it to get Data1D/2D
[8045572]362        Pass it over to the calculator
363        """
364        assert data_item is not None
365
366        if not isinstance(data_item, list):
367            msg = "Incorrect type passed to the P(r) Perspective"
368            raise AttributeError, msg
369
[26f42b1]370        for data in data_item:
[570a2f73]371            # Create initial internal mappings
372            self._data_list[data] = self._calculator.clone()
373            self._data_set = GuiUtils.dataFromItem(data)
374            self.data_plot_list[data] = self.data_plot
375            self.pr_plot_list[data] = self.pr_plot
[dfd8233]376            ref_var = QtCore.QVariant(data)
377            self.populateDataComboBox(self._data_set.filename, ref_var)
[570a2f73]378            self.setCurrentData(data)
379
380            # Estimate initial values from data
381            self.performEstimate()
382            self.logic = InversionLogic(self._data_set)
383
384            # Estimate q range
385            qmin, qmax = self.logic.computeDataRange()
386            self.model.setItem(WIDGETS.W_QMIN, QtGui.QStandardItem(
387                "{:.4g}".format(qmin)))
388            self.model.setItem(WIDGETS.W_QMAX, QtGui.QStandardItem(
389                "{:.4g}".format(qmax)))
390
391        self.enableButtons()
[26f42b1]392
393    def setCurrentData(self, data_ref):
[570a2f73]394        """Get the current data and display as necessary"""
[26f42b1]395
396        if not isinstance(data_ref, QtGui.QStandardItem):
[8045572]397            msg = "Incorrect type passed to the P(r) Perspective"
398            raise AttributeError, msg
399
[26f42b1]400        # Data references
401        self._data = data_ref
402        self._data_set = GuiUtils.dataFromItem(data_ref)
[570a2f73]403        self._calculator = self._data_list[data_ref]
404        self.pr_plot = self.pr_plot_list[data_ref]
405        self.data_plot = self.data_plot_list[data_ref]
[e7651ff]406
[dab3351]407    ######################################################################
408    # Thread Creators
409
[c00a28ff]410    # TODO: Move to individual class(?)
411
412    def startThreadAll(self):
413        for data_ref, pr in self._data_list.items():
414            self._data_set = GuiUtils.dataFromItem(data_ref)
415            self._calculator = pr
416            self.startThread()
417
[dab3351]418    def startThread(self):
419        """
420            Start a calculation thread
421        """
[e7651ff]422        from Thread import CalcPr
[dab3351]423
[c00a28ff]424        # Set data before running the calculations
425        self.update_calculator()
426
427        # If a thread is already started, stop it
428        if self.calc_thread is not None and self.calc_thread.isrunning():
429            self.calc_thread.stop()
430        pr = self._calculator.clone()
431        nfunc = int(UI.TabbedInversionUI._fromUtf8(
432            self.noOfTermsInput.text()))
433        self.calc_thread = CalcPr(pr, nfunc,
434                                  error_func=self._threadError,
435                                  completefn=self._completed, updatefn=None)
436        self.calc_thread.queue()
437        self.calc_thread.ready(2.5)
[dab3351]438
439    def performEstimateNT(self):
440        """
441            Perform parameter estimation
442        """
[e7651ff]443        from Thread import EstimateNT
[dab3351]444
445        # If a thread is already started, stop it
446        if (self.estimation_thread is not None and
447                self.estimation_thread.isrunning()):
448            self.estimation_thread.stop()
449        pr = self._calculator.clone()
450        # Skip the slit settings for the estimation
451        # It slows down the application and it doesn't change the estimates
452        pr.slit_height = 0.0
453        pr.slit_width = 0.0
[57ad773]454        nfunc = int(UI.TabbedInversionUI._fromUtf8(
[dab3351]455            self.noOfTermsInput.text()))
456        self.estimation_thread = EstimateNT(pr, nfunc,
457                                            error_func=self._threadError,
458                                            completefn=self._estimateNTCompleted,
459                                            updatefn=None)
460        self.estimation_thread.queue()
461        self.estimation_thread.ready(2.5)
462
463    def performEstimate(self):
464        """
465            Perform parameter estimation
466        """
[e7651ff]467        from Thread import EstimatePr
468
[dfd8233]469        self.startThread()
[dab3351]470
471        # If a thread is already started, stop it
472        if (self.estimation_thread is not None and
473                self.estimation_thread.isrunning()):
474            self.estimation_thread.stop()
475        pr = self._calculator.clone()
[57ad773]476        nfunc = int(UI.TabbedInversionUI._fromUtf8(
[dab3351]477            self.noOfTermsInput.text()))
478        self.estimation_thread = EstimatePr(pr, nfunc,
479                                            error_func=self._threadError,
480                                            completefn=self._estimateCompleted,
481                                            updatefn=None)
482        self.estimation_thread.queue()
483        self.estimation_thread.ready(2.5)
484
485    ######################################################################
486    # Thread Complete
487
488    def _estimateCompleted(self, alpha, message, elapsed):
489        """
490        Parameter estimation completed,
491        display the results to the user
492
493        :param alpha: estimated best alpha
494        :param elapsed: computation time
495        """
496        # Save useful info
497        self.model.setItem(WIDGETS.W_COMP_TIME,
498                           QtGui.QStandardItem(str(elapsed)))
499        self.regConstantSuggestionButton.setText(QtCore.QString(str(alpha)))
500        self.regConstantSuggestionButton.setEnabled(True)
[d1a4793]501        if message:
[dab3351]502            logging.info(message)
503        self.performEstimateNT()
504
505    def _estimateNTCompleted(self, nterms, alpha, message, elapsed):
506        """
507        Parameter estimation completed,
508        display the results to the user
509
510        :param alpha: estimated best alpha
511        :param nterms: estimated number of terms
512        :param elapsed: computation time
513
514        """
515        # Save useful info
[d1a4793]516        self.noOfTermsSuggestionButton.setText(QtCore.QString(
517            "{:n}".format(nterms)))
[dab3351]518        self.noOfTermsSuggestionButton.setEnabled(True)
[d1a4793]519        self.regConstantSuggestionButton.setText(QtCore.QString(
520            "{:.3g}".format(alpha)))
[dab3351]521        self.regConstantSuggestionButton.setEnabled(True)
522        self.model.setItem(WIDGETS.W_COMP_TIME,
523                           QtGui.QStandardItem(str(elapsed)))
[e7651ff]524        self.PrTabWidget.setCurrentIndex(0)
[d1a4793]525        if message:
[dab3351]526            logging.info(message)
527
528    def _completed(self, out, cov, pr, elapsed):
529        """
530        Method called with the results when the inversion is done
531
532        :param out: output coefficient for the base functions
533        :param cov: covariance matrix
534        :param pr: Invertor instance
535        :param elapsed: time spent computing
536
537        """
538        # Save useful info
539        cov = np.ascontiguousarray(cov)
[57ad773]540        pr.cov = cov
541        pr.out = out
542        pr.elapsed = elapsed
[dab3351]543
544        # Show result on control panel
545
[570a2f73]546        # TODO: Connect self._calculator to GUI - two-to-one connection possible?
[dab3351]547        self.model.setItem(WIDGETS.W_RG, QtGui.QStandardItem(str(pr.rg(out))))
548        self.model.setItem(WIDGETS.W_I_ZERO,
549                           QtGui.QStandardItem(str(pr.iq0(out))))
550        self.model.setItem(WIDGETS.W_BACKGROUND_INPUT,
[d1a4793]551                           QtGui.QStandardItem("{:.3f}".format(pr.background)))
[dab3351]552        self.model.setItem(WIDGETS.W_BACKGROUND_OUTPUT,
553                           QtGui.QStandardItem(str(pr.background)))
554        self.model.setItem(WIDGETS.W_CHI_SQUARED,
[d1a4793]555                           QtGui.QStandardItem(str(pr.chi2[0])))
[dab3351]556        self.model.setItem(WIDGETS.W_COMP_TIME,
557                           QtGui.QStandardItem(str(elapsed)))
558        self.model.setItem(WIDGETS.W_OSCILLATION,
559                           QtGui.QStandardItem(str(pr.oscillations(out))))
560        self.model.setItem(WIDGETS.W_POS_FRACTION,
561                           QtGui.QStandardItem(str(pr.get_positive(out))))
562        self.model.setItem(WIDGETS.W_SIGMA_POS_FRACTION,
563                           QtGui.QStandardItem(str(pr.get_pos_err(out, cov))))
564
[d1a4793]565        # Display results tab
566        self.PrTabWidget.setCurrentIndex(1)
[57ad773]567        # Save Pr invertor
568        self._calculator = pr
569        # Append data to data list
[d132f33]570        self._data_list[self._data] = self._calculator.clone()
[d1a4793]571
[570a2f73]572        # Create new P(r) and fit plots
[57ad773]573        if self.pr_plot is None:
574            self.pr_plot = self.logic.newPRPlot(out, self._calculator, cov)
[570a2f73]575            self.pr_plot_list[self._data] = self.pr_plot
576        else:
577            # FIXME: this should update the existing plot, not create a new one
578            self.pr_plot = self.logic.newPRPlot(out, self._calculator, cov)
579            self.pr_plot_list[self._data] = self.pr_plot
[57ad773]580        if self.data_plot is None:
581            self.data_plot = self.logic.new1DPlot(out, self._calculator)
[570a2f73]582            self.data_plot_list[self._data] = self.data_plot
583        else:
584            # FIXME: this should update the existing plot, not create a new one
585            self.data_plot = self.logic.new1DPlot(out, self._calculator)
586            self.data_plot_list[self._data] = self.data_plot
[dab3351]587
588    def _threadError(self, error):
589        """
590            Call-back method for calculation errors
591        """
592        logging.warning(error)
Note: See TracBrowser for help on using the repository browser.