Changeset 57ad773 in sasview for src/sas/qtgui/Perspectives


Ignore:
Timestamp:
Oct 28, 2017 10:02:15 AM (7 years ago)
Author:
krzywon
Branches:
ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
Children:
d132f33
Parents:
e7651ff
Message:

Plots generated and linked to data set.

Location:
src/sas/qtgui/Perspectives/Inversion
Files:
2 edited
1 moved

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/Perspectives/Inversion/InversionLogic.py

    re7651ff r57ad773  
     1import math 
     2import pylab 
    13import numpy as np 
    24 
    35from sas.qtgui.Plotting.PlotterData import Data1D 
     6 
     7PR_FIT_LABEL = r"$P_{fit}(r)$" 
     8PR_LOADED_LABEL = r"$P_{loaded}(r)$" 
     9IQ_DATA_LABEL = r"$I_{obs}(q)$" 
     10IQ_FIT_LABEL = r"$I_{fit}(q)$" 
     11IQ_SMEARED_LABEL = r"$I_{smeared}(q)$" 
     12GROUP_ID_IQ_DATA = r"$I_{obs}(q)$" 
     13GROUP_ID_PR_FIT = r"$P_{fit}(r)$" 
    414 
    515 
     
    919    No QStandardModelIndex here. 
    1020    """ 
     21 
     22    # TODO: Add way to change this value 
     23    _pr_n_pts = 51 
    1124 
    1225    def __init__(self, data=None): 
     
    3043        return self.data_is_loaded 
    3144 
    32     def new1DPlot(self, return_data): 
     45    def new1DPlot(self, out, pr, q=None): 
    3346        """ 
    3447        Create a new 1D data instance based on fitting results 
    3548        """ 
    36         # Unpack return data from Calc1D 
    37         x, y, page_id, state, weight,\ 
    38         fid, toggle_mode_on, \ 
    39         elapsed, index, model,\ 
    40         data, update_chisqr, source = return_data 
    4149 
    42         # Create the new plot 
    43         new_plot = Data1D(x=x, y=y) 
    44         new_plot.is_data = False 
    45         new_plot.dy = np.zeros(len(y)) 
    46         _yaxis, _yunit = data.get_yaxis() 
    47         _xaxis, _xunit = data.get_xaxis() 
     50        qtemp = pr.x 
     51        if q is not None: 
     52            qtemp = q 
    4853 
    49         new_plot.group_id = data.group_id 
    50         new_plot.id = data.name 
    51         new_plot.name = model.name + " [" + data.name + "]" 
    52         new_plot.title = new_plot.name 
    53         new_plot.xaxis(_xaxis, _xunit) 
    54         new_plot.yaxis(_yaxis, _yunit) 
     54        # Make a plot 
     55        maxq = max(qtemp) 
     56 
     57        minq = min(qtemp) 
     58 
     59        # Check for user min/max 
     60        if pr.q_min is not None and maxq >= pr.q_min >= minq: 
     61            minq = pr.q_min 
     62        if pr.q_max is not None and maxq >= pr.q_max >= minq: 
     63            maxq = pr.q_max 
     64 
     65        x = pylab.arange(minq, maxq, maxq / 301.0) 
     66        y = np.zeros(len(x)) 
     67        err = np.zeros(len(x)) 
     68        for i in range(len(x)): 
     69            value = pr.iq(out, x[i]) 
     70            y[i] = value 
     71            try: 
     72                err[i] = math.sqrt(math.fabs(value)) 
     73            except: 
     74                err[i] = 1.0 
     75                print("Error getting error", value, x[i]) 
     76 
     77        new_plot = Data1D(x, y) 
     78        new_plot.name = IQ_FIT_LABEL 
     79        new_plot.xaxis("\\rm{Q}", 'A^{-1}') 
     80        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 
     81        title = "I(q)" 
     82        new_plot.title = title 
     83 
     84        # If we have a group ID, use it 
     85        if 'plot_group_id' in pr.info: 
     86            new_plot.group_id = pr.info["plot_group_id"] 
     87        new_plot.id = IQ_FIT_LABEL 
     88 
     89        # If we have used slit smearing, plot the smeared I(q) too 
     90        if pr.slit_width > 0 or pr.slit_height > 0: 
     91            x = pylab.arange(minq, maxq, maxq / 301.0) 
     92            y = np.zeros(len(x)) 
     93            err = np.zeros(len(x)) 
     94            for i in range(len(x)): 
     95                value = pr.iq_smeared(pr.out, x[i]) 
     96                y[i] = value 
     97                try: 
     98                    err[i] = math.sqrt(math.fabs(value)) 
     99                except: 
     100                    err[i] = 1.0 
     101                    print("Error getting error", value, x[i]) 
     102 
     103            new_plot = Data1D(x, y) 
     104            new_plot.name = IQ_SMEARED_LABEL 
     105            new_plot.xaxis("\\rm{Q}", 'A^{-1}') 
     106            new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") 
     107            # If we have a group ID, use it 
     108            if 'plot_group_id' in pr.info: 
     109                new_plot.group_id = pr.info["plot_group_id"] 
     110            new_plot.id = IQ_SMEARED_LABEL 
     111            new_plot.title = title 
     112 
     113        return new_plot 
     114 
     115    def newPRPlot(self, out, pr, cov=None): 
     116        """ 
     117        """ 
     118        # Show P(r) 
     119        x = pylab.arange(0.0, pr.d_max, pr.d_max / self._pr_n_pts) 
     120 
     121        y = np.zeros(len(x)) 
     122        dy = np.zeros(len(x)) 
     123        y_true = np.zeros(len(x)) 
     124 
     125        total = 0.0 
     126        pmax = 0.0 
     127        cov2 = np.ascontiguousarray(cov) 
     128 
     129        for i in range(len(x)): 
     130            if cov2 is None: 
     131                value = pr.pr(out, x[i]) 
     132            else: 
     133                (value, dy[i]) = pr.pr_err(out, cov2, x[i]) 
     134            total += value * pr.d_max / len(x) 
     135 
     136            # keep track of the maximum P(r) value 
     137            if value > pmax: 
     138                pmax = value 
     139 
     140            y[i] = value 
     141 
     142        # if self._normalize_output == True: 
     143        #     y = y / total 
     144        #     dy = dy / total 
     145        # elif self._scale_output_unity == True: 
     146        #     y = y / pmax 
     147        #     dy = dy / pmax 
     148 
     149        if cov2 is None: 
     150            new_plot = Data1D(x, y) 
     151        else: 
     152            new_plot = Data1D(x, y, dy=dy) 
     153        new_plot.name = PR_FIT_LABEL 
     154        new_plot.xaxis("\\rm{r}", 'A') 
     155        new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}") 
     156        new_plot.title = "P(r) fit" 
     157        new_plot.id = PR_FIT_LABEL 
     158        # Make sure that the plot is linear 
     159        new_plot.xtransform = "x" 
     160        new_plot.ytransform = "y" 
     161        new_plot.group_id = GROUP_ID_PR_FIT 
    55162 
    56163        return new_plot 
     
    67174        return the npts contains in data 
    68175        """ 
    69         qmin, qmax, npts = None, None, None 
     176        qmin, qmax = None, None 
    70177        if isinstance(data, Data1D): 
    71178            try: 
    72179                qmin = min(data.x) 
    73180                qmax = max(data.x) 
    74                 npts = len(data.x) 
    75181            except (ValueError, TypeError): 
    76182                msg = "Unable to find min/max/length of \n data named %s" % \ 
     
    88194                raise ValueError, msg 
    89195            qmax = np.sqrt(x * x + y * y) 
    90             npts = len(data.data) 
    91         return qmin, qmax, npts 
     196        return qmin, qmax 
  • src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py

    re7651ff r57ad773  
    1212# pr inversion GUI elements 
    1313from InversionUtils import WIDGETS 
    14 import UI.TabbedPrInversionUI 
    15 from UI.TabbedPrInversionUI import Ui_PrInversion 
     14import UI.TabbedInversionUI 
     15from UI.TabbedInversionUI import Ui_PrInversion 
    1616from InversionLogic import InversionLogic 
    1717 
     
    118118        """Connect the use controls to their appropriate methods""" 
    119119        self.enableButtons() 
    120         self.checkBgdClicked(False) 
    121120        # TODO: enable the drop down box once batch is working 
    122121        self.dataList.setEnabled(False) 
     
    130129        self.noOfTermsSuggestionButton.clicked.connect(self.acceptNoTerms) 
    131130        self.explorerButton.clicked.connect(self.openExplorerWindow) 
     131        self.backgroundInput.textChanged.connect( 
     132            lambda: self._calculator.set_est_bck(int(is_float( 
     133                str(self.backgroundInput.text()))))) 
     134        self.minQInput.textChanged.connect( 
     135            lambda: self._calculator.set_qmin(is_float( 
     136                str(self.minQInput.text())))) 
     137        self.regularizationConstantInput.textChanged.connect( 
     138            lambda: self._calculator.set_alpha(is_float( 
     139                str(self.regularizationConstantInput.text())))) 
     140        self.maxDistanceInput.textChanged.connect( 
     141            lambda: self._calculator.set_dmax(is_float( 
     142                str(self.maxDistanceInput.text())))) 
     143        self.maxQInput.textChanged.connect( 
     144            lambda: self._calculator.set_qmax(is_float( 
     145                str(self.maxQInput.text())))) 
     146        self.slitHeightInput.textChanged.connect( 
     147            lambda: self._calculator.set_slit_height(is_float( 
     148                str(self.slitHeightInput.text())))) 
     149        self.slitWidthInput.textChanged.connect( 
     150            lambda: self._calculator.set_slit_width(is_float( 
     151                str(self.slitHeightInput.text())))) 
    132152        self.model.itemChanged.connect(self.model_changed) 
     153        self.estimateBgd.setChecked(True) 
    133154 
    134155    def setupMapper(self): 
     
    255276 
    256277    def update_calculator(self): 
    257         """Update all p(r) params. Take all GUI values as an override""" 
     278        """Update all p(r) params""" 
    258279        self._calculator.set_x(self._data_set.x) 
    259280        self._calculator.set_y(self._data_set.y) 
    260281        self._calculator.set_err(self._data_set.dy) 
    261         self._calculator.set_qmin(is_float(UI.TabbedPrInversionUI._fromUtf8( 
    262             self.minQInput.text()))) 
    263         self._calculator.set_qmax(is_float(UI.TabbedPrInversionUI._fromUtf8( 
    264             self.maxQInput.text()))) 
    265         self._calculator.set_alpha(is_float(UI.TabbedPrInversionUI._fromUtf8( 
    266             self.regularizationConstantInput.text()))) 
    267         self._calculator.set_dmax(is_float(UI.TabbedPrInversionUI._fromUtf8( 
    268             self.maxDistanceInput.text()))) 
    269         self._calculator.set_est_bck(int(is_float( 
    270             UI.TabbedPrInversionUI._fromUtf8(self.backgroundInput.text())))) 
    271         self._calculator.set_slit_height(is_float( 
    272             UI.TabbedPrInversionUI._fromUtf8(self.slitHeightInput.text()))) 
    273         self._calculator.set_slit_width(is_float( 
    274             UI.TabbedPrInversionUI._fromUtf8(self.slitWidthInput.text()))) 
    275282 
    276283    def _calculation(self): 
     
    278285        Calculate the P(r) for every data set in the data list 
    279286        """ 
    280         # Pull in any GUI changes before running the calculations 
     287        # Set data before running the calculations 
    281288        self.update_calculator() 
    282289        # Run 
     
    287294        if not self.mapper: 
    288295            return 
    289         # TODO: Update plots 
     296        if self.pr_plot is not None: 
     297            title = self.pr_plot.name 
     298            GuiUtils.updateModelItemWithPlot( 
     299                self._data, QtCore.QVariant(self.pr_plot), title) 
     300        if self.data_plot is not None: 
     301            title = self.data_plot.name 
     302            GuiUtils.updateModelItemWithPlot( 
     303                self._data, QtCore.QVariant(self.data_plot), title) 
    290304        self.mapper.toFirst() 
    291305 
     
    303317        self._helpView.show() 
    304318 
    305     def checkBgdClicked(self, boolean=None): 
    306         if boolean or self.manualBgd.isChecked(): 
    307             self.manualBgd.setChecked(True) 
    308             self.toggleBgd(self.manualBgd) 
    309         else: 
    310             self.estimateBgd.setChecked(True) 
    311             self.toggleBgd(self.estimateBgd) 
    312  
    313     def toggleBgd(self, item=None): 
     319    def toggleBgd(self): 
    314320        """ 
    315321        Toggle the background between manual and estimated 
    316322        :param item: gui item that was triggered 
    317323        """ 
    318         if not item: 
    319             self.checkBgdClicked() 
    320         elif isinstance(item, QtGui.QRadioButton): 
    321             if item is self.estimateBgd: 
    322                 self.backgroundInput.setEnabled(False) 
    323             else: 
    324                 self.backgroundInput.setEnabled(True) 
     324        sender = self.sender() 
     325        if sender is self.estimateBgd: 
     326            self.backgroundInput.setEnabled(False) 
     327        else: 
     328            self.backgroundInput.setEnabled(True) 
    325329 
    326330    def openExplorerWindow(self): 
     
    353357            self._data = data 
    354358            self._data_set = GuiUtils.dataFromItem(data) 
    355             self.enableButtons() 
    356359            self.populateDataComboBox(self._data_set.filename) 
    357360 
    358361            # Estimate initial values from data 
    359362            self.performEstimate() 
    360             self.logic.data(self._calculator) 
    361  
    362             self._manager.createGuiData(None) 
    363  
    364             # TODO: Finish plotting 
    365             if self.pr_plot is None: 
    366                 self.pr_plot = None 
    367                 #self.pr_plot = self.logic.new1DPlot(self._calculator) 
    368             if self.data_plot is None: 
    369                 self.data_plot = None 
    370  
    371             qmin, qmax, _ = self.logic.computeDataRange() 
    372             title = self._data.filename 
     363            self.logic = InversionLogic(self._data_set) 
     364 
     365            qmin, qmax = self.logic.computeDataRange() 
    373366 
    374367            self.model.setItem(WIDGETS.W_QMIN, QtGui.QStandardItem( 
     
    376369            self.model.setItem(WIDGETS.W_QMAX, QtGui.QStandardItem( 
    377370                "{:.4g}".format(qmax))) 
    378             #reactor.callFromThread(GuiUtils.updateModelItemWithPlot, 
    379             #                       self._model_item, self._communicator, title) 
     371 
     372            self.enableButtons() 
    380373 
    381374            # TODO: Only load 1st data until batch mode working. Thus, break 
     
    395388            self.calc_thread.stop() 
    396389        pr = self._calculator.clone() 
    397         nfunc = int(UI.TabbedPrInversionUI._fromUtf8( 
     390        nfunc = int(UI.TabbedInversionUI._fromUtf8( 
    398391            self.noOfTermsInput.text())) 
    399392        self.calc_thread = CalcPr(pr, nfunc, 
     
    418411        pr.slit_height = 0.0 
    419412        pr.slit_width = 0.0 
    420         nfunc = int(UI.TabbedPrInversionUI._fromUtf8( 
     413        nfunc = int(UI.TabbedInversionUI._fromUtf8( 
    421414            self.noOfTermsInput.text())) 
    422415        self.estimation_thread = EstimateNT(pr, nfunc, 
     
    440433            self.estimation_thread.stop() 
    441434        pr = self._calculator.clone() 
    442         nfunc = int(UI.TabbedPrInversionUI._fromUtf8( 
     435        nfunc = int(UI.TabbedInversionUI._fromUtf8( 
    443436            self.noOfTermsInput.text())) 
    444437        self.estimation_thread = EstimatePr(pr, nfunc, 
     
    503496        """ 
    504497        # Save useful info 
    505         # Keep a copy of the last result 
    506         self._last_calculator = pr.clone() 
    507  
    508         # Save Pr invertor 
    509         self._calculator = pr 
    510498        cov = np.ascontiguousarray(cov) 
     499        pr.cov = cov 
     500        pr.out = out 
     501        pr.elapsed = elapsed 
    511502 
    512503        # Show result on control panel 
     
    533524        # Display results tab 
    534525        self.PrTabWidget.setCurrentIndex(1) 
     526        # Save Pr invertor 
     527        self._calculator = pr 
     528        # Append data to data list 
    535529        self._data_list.append({self._data: pr}) 
    536530 
    537         # TODO: Show plots - Really, this should be linked to the inputs, etc, 
    538         # TODO: so it should happen automagically 
    539         # Show I(q) fit 
    540         # self.show_iq(out, self._calculator) 
    541         # Show P(r) fit 
    542         # self.show_pr(out, self._calculator, cov) 
     531        if self.pr_plot is None: 
     532            self.pr_plot = self.logic.newPRPlot(out, self._calculator, cov) 
     533        if self.data_plot is None: 
     534            self.data_plot = self.logic.new1DPlot(out, self._calculator) 
    543535 
    544536    def _threadError(self, error): 
Note: See TracChangeset for help on using the changeset viewer.