Changeset c1bc9de in sasview


Ignore:
Timestamp:
Sep 19, 2018 9:33:59 AM (3 months ago)
Author:
wojciech
Branches:
ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_ordering
Children:
bdfe0be
Parents:
dee9e5f (diff), d1e4689 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'ESS_GUI' of https://github.com/SasView/sasview into ESS_GUI_Pr_fixes

Location:
src/sas
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r9ce69ec rd1e4689  
    10721072            if not self.rowHasConstraint(row): 
    10731073                return 
     1074            constr = self.getConstraintForRow(row) 
    10741075            func = self.getConstraintForRow(row).func 
    1075             if func is not None: 
    1076                 self.communicate.statusBarUpdateSignal.emit("Active constrain: "+func) 
     1076            if constr.func is not None: 
     1077                # inter-parameter constraint 
     1078                update_text = "Active constraint: "+func 
     1079            elif constr.param == rows[0].data(): 
     1080                # current value constraint 
     1081                update_text = "Value constrained to: " + str(constr.value) 
     1082            else: 
     1083                # ill defined constraint 
     1084                return 
     1085            self.communicate.statusBarUpdateSignal.emit(update_text) 
    10771086 
    10781087    def replaceConstraintName(self, old_name, new_name=""): 
     
    18221831        self.cmdPlot.setText("Show Plot") 
    18231832        # Force data recalculation so existing charts are updated 
    1824         self.showPlot() 
     1833        if not self.data_is_loaded: 
     1834            self.showTheoryPlot() 
     1835        else: 
     1836            self.showPlot() 
    18251837        # This is an important processEvent. 
    18261838        # This allows charts to be properly updated in order 
     
    18431855        self.calculateQGridForModel() 
    18441856 
     1857    def showTheoryPlot(self): 
     1858        """ 
     1859        Show the current theory plot in MPL 
     1860        """ 
     1861        # Show the chart if ready 
     1862        data_to_show = self.model_data 
     1863        if self.theory_item is None: 
     1864            self.recalculatePlotData() 
     1865        else: 
     1866            self.communicate.plotRequestedSignal.emit([self.theory_item, data_to_show], self.tab_id) 
     1867 
    18451868    def showPlot(self): 
    18461869        """ 
     
    18481871        """ 
    18491872        # Show the chart if ready 
    1850         data_to_show = self.data if self.data_is_loaded else self.model_data 
     1873        data_to_show = self.data 
    18511874        # Any models for this page 
    18521875        current_index = self.all_data[self.data_index] 
     1876        fitpage_name = "" if id is None else "M"+str(self.tab_id) 
    18531877        plots = GuiUtils.plotsFromFilename(self.data.filename, current_index.model()) 
    1854         fitpage_name = "" if id is None else "M"+str(self.tab_id) 
    18551878        # Has the fitted data been shown? 
    18561879        data_shown = False 
     
    24492472            return 
    24502473        fitted_data = self.logic.new1DPlot(return_data, self.tab_id) 
     2474        if len(fitted_data.x) != len(self.data.x): 
     2475            return 
     2476 
    24512477        residuals = self.calculateResiduals(fitted_data) 
    24522478        self.model_data = fitted_data 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py

    r1a15ada rd1e4689  
    620620        # Set to 0 
    621621        self.widget.lstParams.indexWidget(func_index).setCurrentIndex(0) 
    622         self.assertEqual(self.widget._model_model.rowCount(), last_row - 2) # 2 fewer rows than default 
     622        self.assertEqual(self.widget._model_model.rowCount(), last_row - 2) 
    623623 
    624624    def testPlotTheory(self): 
     
    658658        self.assertEqual(spy.count(), 0) 
    659659 
    660     def testPlotData(self): 
     660    def notestPlotData(self): 
    661661        """ 
    662662        See that data item can produce a chart 
  • src/sas/qtgui/GUITests.py

    r7dd309a rccd2b87  
    180180        unittest.makeSuite(InvariantPerspectiveTest.InvariantPerspectiveTest,  'test'), 
    181181        #  Inversion 
    182         #unittest.makeSuite(InversionPerspectiveTest.InversionTest,  'test'), 
     182        unittest.makeSuite(InversionPerspectiveTest.InversionTest,  'test'), 
    183183        ) 
    184184    return unittest.TestSuite(suites) 
  • src/sas/qtgui/MainWindow/GuiManager.py

    rfc5d2d7f rdee9e5f  
    992992        When setting a perspective, sets up the menu bar 
    993993        """ 
     994        self._workspace.actionReport.setEnabled(False) 
    994995        if isinstance(perspective, Perspectives.PERSPECTIVES["Fitting"]): 
    995996            self.checkAnalysisOption(self._workspace.actionFitting) 
     
    10011002            self._workspace.menubar.addAction(self._workspace.menuWindow.menuAction()) 
    10021003            self._workspace.menubar.addAction(self._workspace.menuHelp.menuAction()) 
     1004            self._workspace.actionReport.setEnabled(True) 
    10031005 
    10041006        elif isinstance(perspective, Perspectives.PERSPECTIVES["Invariant"]): 
  • src/sas/qtgui/Perspectives/Inversion/DMaxExplorerWidget.py

    rb0ba43e r9f2f713  
    4242        self.parent = parent 
    4343 
    44         self.setWindowTitle("Dₐₓ Explorer") 
     44        self.setWindowTitle("Dmax Explorer") 
    4545 
    4646        self.pr_state = pr_state 
     
    116116        bck = [] 
    117117        chi2 = [] 
    118  
     118        plotable_xs = [] #Introducing this to make sure size of x and y for plotting is the same.8 
    119119        try: 
    120120            dmin = float(self.model.item(W.DMIN).text()) 
     
    128128 
    129129        original = self.pr_state.d_max 
     130 
    130131        for x in xs: 
    131132            self.pr_state.d_max = x 
     
    140141                bck.append(self.pr_state.background) 
    141142                chi2.append(self.pr_state.chi2) 
     143                plotable_xs.append(x) 
    142144            except Exception as ex: 
    143145                # This inversion failed, skip this D_max value 
     
    155157            logger.error(msg) 
    156158 
    157         plotter = self.model.item(W.VARIABLE).text() 
    158         y_label = y_unit = "" 
     159        plotter = self.dependentVariable.currentText() 
    159160        x_label = "D_{max}" 
    160161        x_unit = "A" 
     
    188189            y_unit = "a.u." 
    189190 
    190         data = Data1D(xs, ys) 
     191        data = Data1D(plotable_xs, ys) 
    191192        if self.hasPlot: 
    192             self.plot.removePlot(None) 
     193            self.plot.removePlot(data.name) 
    193194        self.hasPlot = True 
    194195        data.title = plotter 
  • src/sas/qtgui/Perspectives/Inversion/InversionLogic.py

    r6da860a r3c4f02e  
    111111            new_plot.title = title 
    112112 
     113        new_plot.symbol = 'Line' 
     114        new_plot.hide_error = True 
     115 
    113116        return new_plot 
    114117 
  • src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py

    r9ce69ec rdee9e5f  
    4444    estimateSignal = QtCore.pyqtSignal(tuple) 
    4545    estimateNTSignal = QtCore.pyqtSignal(tuple) 
     46    estimateDynamicNTSignal = QtCore.pyqtSignal(tuple) 
     47    estimateDynamicSignal = QtCore.pyqtSignal(tuple) 
    4648    calculateSignal = QtCore.pyqtSignal(tuple) 
    4749 
     
    5355 
    5456        self._manager = parent 
     57        #Needed for Batch fitting 
     58        self._parent = parent 
    5559        self.communicate = parent.communicator() 
    5660        self.communicate.dataDeletedSignal.connect(self.removeData) 
     
    110114        # Set up the Widget Map 
    111115        self.setupMapper() 
     116 
     117        #Hidding calculate all buton 
     118        self.calculateAllButton.setVisible(False) 
    112119        # Set base window state 
    113120        self.setupWindow() 
     
    120127 
    121128    def allowBatch(self): 
    122         return True 
     129        return False 
    123130 
    124131    def setClosable(self, value=True): 
     
    195202        self.model.itemChanged.connect(self.model_changed) 
    196203        self.estimateNTSignal.connect(self._estimateNTUpdate) 
     204        self.estimateDynamicNTSignal.connect(self._estimateDynamicNTUpdate) 
     205        self.estimateDynamicSignal.connect(self._estimateDynamicUpdate) 
    197206        self.estimateSignal.connect(self._estimateUpdate) 
    198207        self.calculateSignal.connect(self._calculateUpdate) 
     208 
     209        self.maxDistanceInput.textEdited.connect(self.performEstimateDynamic) 
    199210 
    200211    def setupMapper(self): 
     
    310321                                            and not self.isCalculating) 
    311322        self.removeButton.setEnabled(self.logic.data_is_loaded) 
    312         self.explorerButton.setEnabled(self.logic.data_is_loaded 
    313                                        and np.all(self.logic.data.dy != 0)) 
     323        self.explorerButton.setEnabled(self.logic.data_is_loaded) 
    314324        self.stopButton.setVisible(self.isCalculating) 
    315325        self.regConstantSuggestionButton.setEnabled( 
     
    454464            # Create initial internal mappings 
    455465            self.logic.data = GuiUtils.dataFromItem(data) 
     466            if not isinstance(self.logic.data, Data1D): 
     467                msg = "P(r) perspective works for 1D data only" 
     468                logger.warning(msg) 
     469                continue 
    456470            # Estimate q range 
    457471            qmin, qmax = self.logic.computeDataRange() 
    458472            self._calculator.set_qmin(qmin) 
    459473            self._calculator.set_qmax(qmax) 
     474            if np.size(self.logic.data.dy) == 0 or np.all(self.logic.data.dy) == 0: 
     475                self.logic.data.dy = self._calculator.add_errors(self.logic.data.y) 
    460476            self.updateDataList(data) 
    461477            self.populateDataComboBox(self.logic.data.filename, data) 
    462478        self.dataList.setCurrentIndex(len(self.dataList) - 1) 
    463         self.setCurrentData(data) 
     479        #Checking for 1D again to mitigate the case when 2D data is last on the data list 
     480        if isinstance(self.logic.data, Data1D): 
     481            self.setCurrentData(data) 
    464482 
    465483    def updateDataList(self, dataRef): 
     
    502520        self.dataPlot = self._dataList[data_ref].get(DICT_KEYS[2]) 
    503521        self.performEstimate() 
     522 
     523    def updateDynamicGuiValues(self): 
     524        pr = self._calculator 
     525        alpha = self._calculator.suggested_alpha 
     526        self.model.setItem(WIDGETS.W_MAX_DIST, 
     527                            QtGui.QStandardItem("{:.4g}".format(pr.get_dmax()))) 
     528        self.regConstantSuggestionButton.setText("{:-3.2g}".format(alpha)) 
     529        self.noOfTermsSuggestionButton.setText( 
     530             "{:n}".format(self.nTermsSuggested)) 
     531 
     532        self.enableButtons() 
    504533 
    505534    def updateGuiValues(self): 
     
    521550        self.model.setItem(WIDGETS.W_MAX_DIST, 
    522551                           QtGui.QStandardItem("{:.4g}".format(pr.get_dmax()))) 
    523         self.regConstantSuggestionButton.setText("{:-3.2g}".format(alpha)) 
    524         self.noOfTermsSuggestionButton.setText( 
    525             "{:n}".format(self.nTermsSuggested)) 
    526552 
    527553        if isinstance(pr.chi2, np.ndarray): 
     
    638664 
    639665        pr = self._calculator.clone() 
    640         nfunc = self.getNFunc() 
    641         self.calcThread = CalcPr(pr, nfunc, 
     666        #Making sure that nfunc and alpha parameters are correctly initialized 
     667        pr.suggested_alpha = self._calculator.alpha 
     668        self.calcThread = CalcPr(pr, self.nTermsSuggested, 
    642669                                 error_func=self._threadError, 
    643670                                 completefn=self._calculateCompleted, 
     
    672699                                             error_func=self._threadError, 
    673700                                             completefn=self._estimateNTCompleted, 
     701                                             updatefn=None) 
     702        self.estimationThreadNT.queue() 
     703        self.estimationThreadNT.ready(2.5) 
     704 
     705    def performEstimateDynamicNT(self): 
     706        """ 
     707        Perform parameter estimation 
     708        """ 
     709        from .Thread import EstimateNT 
     710 
     711        self.updateCalculator() 
     712 
     713        # If a thread is already started, stop it 
     714        self.stopEstimateNTThread() 
     715 
     716        pr = self._calculator.clone() 
     717        # Skip the slit settings for the estimation 
     718        # It slows down the application and it doesn't change the estimates 
     719        pr.slit_height = 0.0 
     720        pr.slit_width = 0.0 
     721        nfunc = self.getNFunc() 
     722 
     723        self.estimationThreadNT = EstimateNT(pr, nfunc, 
     724                                             error_func=self._threadError, 
     725                                             completefn=self._estimateDynamicNTCompleted, 
    674726                                             updatefn=None) 
    675727        self.estimationThreadNT.queue() 
     
    698750        self.estimationThread.ready(2.5) 
    699751 
     752    def performEstimateDynamic(self): 
     753        """ 
     754            Perform parameter estimation 
     755        """ 
     756        from .Thread import EstimatePr 
     757 
     758        # If a thread is already started, stop it 
     759        self.stopEstimationThread() 
     760 
     761        self.estimationThread = EstimatePr(self._calculator.clone(), 
     762                                           self.getNFunc(), 
     763                                           error_func=self._threadError, 
     764                                           completefn=self._estimateDynamicCompleted, 
     765                                           updatefn=None) 
     766        self.estimationThread.queue() 
     767        self.estimationThread.ready(2.5) 
     768 
    700769    def stopEstimationThread(self): 
    701770        """ Stop the estimation thread if it exists and is running """ 
     
    710779        ''' Send a signal to the main thread for model update''' 
    711780        self.estimateSignal.emit((alpha, message, elapsed)) 
     781 
     782    def _estimateDynamicCompleted(self, alpha, message, elapsed): 
     783        ''' Send a signal to the main thread for model update''' 
     784        self.estimateDynamicSignal.emit((alpha, message, elapsed)) 
    712785 
    713786    def _estimateUpdate(self, output_tuple): 
     
    725798            logger.info(message) 
    726799        self.performEstimateNT() 
     800        self.performEstimateDynamicNT() 
     801 
     802    def _estimateDynamicUpdate(self, output_tuple): 
     803        """ 
     804        Parameter estimation completed, 
     805        display the results to the user 
     806 
     807        :param alpha: estimated best alpha 
     808        :param elapsed: computation time 
     809        """ 
     810        alpha, message, elapsed = output_tuple 
     811        self._calculator.alpha = alpha 
     812        self._calculator.elapsed += self._calculator.elapsed 
     813        if message: 
     814            logger.info(message) 
     815        self.performEstimateDynamicNT() 
    727816 
    728817    def _estimateNTCompleted(self, nterms, alpha, message, elapsed): 
    729818        ''' Send a signal to the main thread for model update''' 
    730819        self.estimateNTSignal.emit((nterms, alpha, message, elapsed)) 
     820 
     821    def _estimateDynamicNTCompleted(self, nterms, alpha, message, elapsed): 
     822        ''' Send a signal to the main thread for model update''' 
     823        self.estimateDynamicNTSignal.emit((nterms, alpha, message, elapsed)) 
    731824 
    732825    def _estimateNTUpdate(self, output_tuple): 
     
    752845            self.startThread() 
    753846 
     847    def _estimateDynamicNTUpdate(self, output_tuple): 
     848        """ 
     849        Parameter estimation completed, 
     850        display the results to the user 
     851 
     852        :param alpha: estimated best alpha 
     853        :param nterms: estimated number of terms 
     854        :param elapsed: computation time 
     855        """ 
     856        nterms, alpha, message, elapsed = output_tuple 
     857        self._calculator.elapsed += elapsed 
     858        self._calculator.suggested_alpha = alpha 
     859        self.nTermsSuggested = nterms 
     860        # Save useful info 
     861        self.updateDynamicGuiValues() 
     862        if message: 
     863            logger.info(message) 
     864        if self.isBatch: 
     865            self.acceptAlpha() 
     866            self.acceptNoTerms() 
     867            self.startThread() 
     868 
    754869    def _calculateCompleted(self, out, cov, pr, elapsed): 
    755870        ''' Send a signal to the main thread for model update''' 
  • src/sas/qtgui/Perspectives/Inversion/UI/DMaxExplorer.ui

    r8f83719f rcfd61f2  
    77    <x>0</x> 
    88    <y>0</y> 
    9     <width>394</width> 
    10     <height>426</height> 
     9    <width>586</width> 
     10    <height>538</height> 
    1111   </rect> 
    1212  </property> 
     
    2121       <property name="orientation"> 
    2222        <enum>Qt::Vertical</enum> 
    23        </property> 
    24        <property name="sizeHint" stdset="0"> 
    25         <size> 
    26          <width>20</width> 
    27          <height>305</height> 
    28         </size> 
    2923       </property> 
    3024      </spacer> 
  • src/sas/qtgui/Perspectives/Inversion/UI/TabbedInversionUI.ui

    r72ecbdf2 r68dc2873  
    77    <x>0</x> 
    88    <y>0</y> 
    9     <width>390</width> 
    10     <height>409</height> 
     9    <width>446</width> 
     10    <height>480</height> 
    1111   </rect> 
    1212  </property> 
     
    740740      <widget class="QPushButton" name="calculateAllButton"> 
    741741       <property name="enabled"> 
    742         <bool>true</bool> 
     742        <bool>false</bool> 
    743743       </property> 
    744744       <property name="sizePolicy"> 
  • src/sas/qtgui/Perspectives/Inversion/UnitTesting/InversionPerspectiveTest.py

    r144fe21 rccd2b87  
    9999    def baseBatchState(self): 
    100100        """ Testing the base batch fitting state """ 
    101         self.assertTrue(self.widget.allowBatch()) 
     101        self.assertFalse(self.widget.allowBatch()) 
    102102        self.assertFalse(self.widget.isBatch) 
    103103        self.assertFalse(self.widget.calculateAllButton.isEnabled()) 
     
    304304        self.assertIsNotNone(self.widget.dmaxWindow) 
    305305        self.assertTrue(self.widget.dmaxWindow.isVisible()) 
    306         self.assertTrue(self.widget.dmaxWindow.windowTitle() == "Dₐₓ Explorer") 
     306        self.assertTrue(self.widget.dmaxWindow.windowTitle() == "Dmax Explorer") 
    307307 
    308308 
  • src/sas/qtgui/Plotting/Plotter.py

    r5b144c6 rd0952de  
    8484            if self.data.ytransform is None: 
    8585                self.data.ytransform = 'log10(y)' 
    86  
     86            #Added condition to Dmax explorer from P(r) perspective 
     87            if self.data._xaxis == 'D_{max}': 
     88                self.xscale = 'linear' 
    8789            # Transform data if required. 
    8890            if transform and (self.data.xtransform is not None or self.data.ytransform is not None): 
  • src/sas/qtgui/Utilities/GridPanel.py

    r3c6ecd9 r4fbf0db  
    5454        # Fill in the table from input data 
    5555        self.setupTable(widget=self.tblParams, data=output_data) 
     56        #TODO: This is not what was inteded to be. 
    5657        if output_data is not None: 
    5758            # Set a table tooltip describing the model 
    58             model_name = output_data[0][0].model.id 
     59            model_name = list(output_data.keys())[0] 
    5960            self.tabWidget.setTabToolTip(0, model_name) 
    6061 
     
    418419    def __init__(self, parent = None, output_data=None): 
    419420 
    420         super(BatchInversionOutputPanel, self).__init__(parent, output_data) 
     421        super(BatchInversionOutputPanel, self).__init__(parent._parent, output_data) 
    421422        _translate = QtCore.QCoreApplication.translate 
    422423        self.setWindowTitle(_translate("GridPanelUI", "Batch P(r) Results")) 
    423424 
    424     def setupTable(self, data): 
     425    def setupTable(self, widget=None,  data=None): 
    425426        """ 
    426427        Create tablewidget items and show them, based on params 
     
    433434                      'Calc. Time [sec]'] 
    434435 
     436        if data is None: 
     437            return 
    435438        keys = data.keys() 
    436439        rows = len(keys) 
  • src/sas/sascalc/pr/invertor.py

    rb8080e1 reeea6a3  
    7171        A[j][i] = (Fourier transformed base function for point j) 
    7272 
    73     We them choose a number of r-points, n_r, to evaluate the second 
     73    We then choose a number of r-points, n_r, to evaluate the second 
    7474    derivative of P(r) at. This is used as our regularization term. 
    7575    For a vector r of length n_r, the following n_r rows are set to :: 
     
    144144        x, y, err, d_max, q_min, q_max and alpha 
    145145        """ 
    146         if   name == 'x': 
     146        if name == 'x': 
    147147            if 0.0 in value: 
    148148                msg = "Invertor: one of your q-values is zero. " 
     
    227227        return None 
    228228 
     229    def add_errors(self, yvalues): 
     230        """ 
     231        Adds errors to data set is they are not avaialble 
     232        :return: 
     233        """ 
     234        stats_errors = np.zeros(len(yvalues)) 
     235        for i in range(len(yvalues)): 
     236            # Scale the error so that we can fit over several decades of Q 
     237            scale = 0.05 * np.sqrt(yvalues[i]) 
     238            min_err = 0.01 * yvalues[i] 
     239            stats_errors[i] = scale * np.sqrt(np.fabs(yvalues[i])) + min_err 
     240        logger.warning("Simulated errors have been added to the data set\n") 
     241        return stats_errors 
     242 
    229243    def clone(self): 
    230244        """ 
     
    268282            A[i][j] = (Fourier transformed base function for point j) 
    269283 
    270         We them choose a number of r-points, n_r, to evaluate the second 
     284        We then choose a number of r-points, n_r, to evaluate the second 
    271285        derivative of P(r) at. This is used as our regularization term. 
    272286        For a vector r of length n_r, the following n_r rows are set to :: 
Note: See TracChangeset for help on using the changeset viewer.